@imdeadpool/guardex 7.0.21 → 7.0.22

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/src/context.js CHANGED
@@ -348,7 +348,7 @@ const CLI_COMMAND_DESCRIPTIONS = [
348
348
  ['cleanup', 'Prune merged/stale agent branches and worktrees'],
349
349
  ['release', 'Create or update the current GitHub release with README-generated notes'],
350
350
  ['agents', 'Start/stop repo-scoped review + cleanup bots'],
351
- ['prompt', 'Print AI setup checklist (--exec, --snippet)'],
351
+ ['prompt', 'Print AI setup checklist or named slices (--exec, --part, --list-parts, --snippet)'],
352
352
  ['report', 'Security/safety reports (e.g. OpenSSF scorecard)'],
353
353
  ['help', 'Show this help output'],
354
354
  ['version', 'Print GitGuardex version'],
@@ -369,6 +369,12 @@ const AGENT_BOT_DESCRIPTIONS = [
369
369
  const DOCTOR_AUTO_FINISH_DETAIL_LIMIT = 6;
370
370
  const DOCTOR_AUTO_FINISH_BRANCH_LABEL_MAX = 72;
371
371
  const DOCTOR_AUTO_FINISH_MESSAGE_MAX = 160;
372
+ const AI_SETUP_PART_ALIASES = new Map([
373
+ ['task', 'task-loop'],
374
+ ['loop', 'task-loop'],
375
+ ['reviewbot', 'review-bot'],
376
+ ['forksync', 'fork-sync'],
377
+ ]);
372
378
 
373
379
  function envFlagIsTruthy(raw) {
374
380
  const lowered = String(raw || '').trim().toLowerCase();
@@ -383,35 +389,176 @@ function defaultAgentWorktreeRelativeDir(env = process.env) {
383
389
  return isClaudeCodeSession(env) ? CLAUDE_WORKTREE_RELATIVE_DIR : CODEX_WORKTREE_RELATIVE_DIR;
384
390
  }
385
391
 
386
- const AI_SETUP_PROMPT = `GitGuardex (gx) setup checklist for Codex/Claude in this repo.
387
-
388
- 1) Install: ${GLOBAL_INSTALL_COMMAND} && gh --version
389
- 2) Bootstrap: gx setup
390
- 3) Repair: gx doctor
391
- 4) Task loop: gx branch start "<task>" "<agent>"
392
- then gx locks claim --branch "<agent-branch>" <file...> -> gx branch finish
393
- 5) Integrate: gx merge --branch <agent-a> --branch <agent-b>
394
- 6) Finish: gx finish --all
395
- 7) Cleanup: gx cleanup
396
- 8) OpenSpec: /opsx:propose -> /opsx:apply -> /opsx:archive
397
- 9) Optional: gx protect add release staging
398
- 10) Optional: gx sync --check && gx sync
399
- 11) Review bot: install https://github.com/apps/cr-gpt + set OPENAI_API_KEY
400
- 12) Fork sync: install https://github.com/apps/pull + cp .github/pull.yml.example .github/pull.yml
401
- `;
402
-
403
- const AI_SETUP_COMMANDS = `${GLOBAL_INSTALL_COMMAND}
404
- gh --version
405
- gx setup
406
- gx doctor
407
- gx branch start "<task>" "<agent>"
408
- gx locks claim --branch "<agent-branch>" <file...>
409
- gx merge --branch "<agent-a>" --branch "<agent-b>"
410
- gx finish --all
411
- gx cleanup
412
- gx protect add release staging
413
- gx sync --check && gx sync
414
- `;
392
+ const AI_SETUP_PARTS = [
393
+ {
394
+ name: 'install',
395
+ label: 'Install',
396
+ promptLines: [`${GLOBAL_INSTALL_COMMAND} && gh --version`],
397
+ execLines: [GLOBAL_INSTALL_COMMAND, 'gh --version'],
398
+ },
399
+ {
400
+ name: 'bootstrap',
401
+ label: 'Bootstrap',
402
+ promptLines: ['gx setup'],
403
+ execLines: ['gx setup'],
404
+ },
405
+ {
406
+ name: 'repair',
407
+ label: 'Repair',
408
+ promptLines: ['gx doctor'],
409
+ execLines: ['gx doctor'],
410
+ },
411
+ {
412
+ name: 'task-loop',
413
+ label: 'Task loop',
414
+ promptLines: [
415
+ 'gx branch start "<task>" "<agent>"',
416
+ 'then gx locks claim --branch "<agent-branch>" <file...> -> gx branch finish',
417
+ ],
418
+ execLines: [
419
+ 'gx branch start "<task>" "<agent>"',
420
+ 'gx locks claim --branch "<agent-branch>" <file...>',
421
+ ],
422
+ },
423
+ {
424
+ name: 'integrate',
425
+ label: 'Integrate',
426
+ promptLines: ['gx merge --branch <agent-a> --branch <agent-b>'],
427
+ execLines: ['gx merge --branch <agent-a> --branch <agent-b>'],
428
+ },
429
+ {
430
+ name: 'finish',
431
+ label: 'Finish',
432
+ promptLines: ['gx finish --all'],
433
+ execLines: ['gx finish --all'],
434
+ },
435
+ {
436
+ name: 'cleanup',
437
+ label: 'Cleanup',
438
+ promptLines: ['gx cleanup'],
439
+ execLines: ['gx cleanup'],
440
+ },
441
+ {
442
+ name: 'openspec',
443
+ label: 'OpenSpec',
444
+ promptLines: ['/opsx:propose -> /opsx:apply -> /opsx:archive'],
445
+ },
446
+ {
447
+ name: 'protect',
448
+ label: 'Protect',
449
+ promptLines: ['gx protect add release staging'],
450
+ execLines: ['gx protect add release staging'],
451
+ },
452
+ {
453
+ name: 'sync',
454
+ label: 'Sync',
455
+ promptLines: ['gx sync --check && gx sync'],
456
+ execLines: ['gx sync --check && gx sync'],
457
+ },
458
+ {
459
+ name: 'review-bot',
460
+ label: 'Review bot',
461
+ promptLines: ['install https://github.com/apps/cr-gpt + set OPENAI_API_KEY'],
462
+ },
463
+ {
464
+ name: 'fork-sync',
465
+ label: 'Fork sync',
466
+ promptLines: ['install https://github.com/apps/pull + cp .github/pull.yml.example .github/pull.yml'],
467
+ },
468
+ ];
469
+ const AI_SETUP_PARTS_BY_NAME = new Map(AI_SETUP_PARTS.map((part) => [part.name, part]));
470
+ const AI_SETUP_EXEC_PART_NAMES = AI_SETUP_PARTS
471
+ .filter((part) => Array.isArray(part.execLines))
472
+ .map((part) => part.name);
473
+
474
+ function normalizeAiSetupPartName(rawName) {
475
+ const normalized = String(rawName || '')
476
+ .trim()
477
+ .toLowerCase()
478
+ .replace(/_/g, '-');
479
+ return AI_SETUP_PART_ALIASES.get(normalized) || normalized;
480
+ }
481
+
482
+ function listAiSetupPartNames(options = {}) {
483
+ if (!options.execOnly) return AI_SETUP_PARTS.map((part) => part.name);
484
+ return AI_SETUP_EXEC_PART_NAMES.slice();
485
+ }
486
+
487
+ function parseAiSetupPartNames(rawValue) {
488
+ return String(rawValue || '')
489
+ .split(',')
490
+ .map((entry) => normalizeAiSetupPartName(entry))
491
+ .filter(Boolean);
492
+ }
493
+
494
+ function resolveAiSetupParts(rawPartNames, options = {}) {
495
+ const exec = Boolean(options.exec);
496
+ const requestedPartNames = Array.isArray(rawPartNames) ? rawPartNames : [];
497
+ const availablePartNames = listAiSetupPartNames();
498
+ const execCapablePartNames = listAiSetupPartNames({ execOnly: true });
499
+ const seen = new Set();
500
+ const resolved = [];
501
+
502
+ for (const rawName of requestedPartNames) {
503
+ const name = normalizeAiSetupPartName(rawName);
504
+ const part = AI_SETUP_PARTS_BY_NAME.get(name);
505
+ if (!part) {
506
+ throw new Error(
507
+ `Unknown prompt part: ${rawName}. Available parts: ${availablePartNames.join(', ')}`,
508
+ );
509
+ }
510
+ if (exec && !Array.isArray(part.execLines)) {
511
+ throw new Error(
512
+ `Prompt part '${name}' is not available with --exec. ` +
513
+ `Exec-capable parts: ${execCapablePartNames.join(', ')}`,
514
+ );
515
+ }
516
+ if (seen.has(name)) continue;
517
+ seen.add(name);
518
+ resolved.push(part);
519
+ }
520
+
521
+ return resolved;
522
+ }
523
+
524
+ function renderFullAiSetupPrompt() {
525
+ const lines = ['GitGuardex (gx) setup checklist for Codex/Claude in this repo.', ''];
526
+ const indentWidth = 18;
527
+
528
+ AI_SETUP_PARTS.forEach((part, index) => {
529
+ const [lead, ...tail] = part.promptLines;
530
+ const prefix = `${index + 1}) ${part.label}:`;
531
+ lines.push(`${prefix.padEnd(indentWidth)}${lead}`);
532
+ tail.forEach((line) => lines.push(`${' '.repeat(indentWidth)}${line}`));
533
+ });
534
+
535
+ return `${lines.join('\n')}\n`;
536
+ }
537
+
538
+ function renderPartialAiSetupPrompt(parts) {
539
+ return `${parts
540
+ .map((part) => `${part.label}:\n${part.promptLines.join('\n')}`)
541
+ .join('\n\n')}\n`;
542
+ }
543
+
544
+ function renderAiSetupCommands(parts) {
545
+ return `${parts.flatMap((part) => part.execLines).join('\n')}\n`;
546
+ }
547
+
548
+ function renderAiSetupPrompt(options = {}) {
549
+ const exec = Boolean(options.exec);
550
+ const requestedPartNames = Array.isArray(options.parts) ? options.parts : [];
551
+ if (requestedPartNames.length === 0) {
552
+ return exec
553
+ ? renderAiSetupCommands(resolveAiSetupParts(AI_SETUP_EXEC_PART_NAMES, { exec: true }))
554
+ : renderFullAiSetupPrompt();
555
+ }
556
+ const parts = resolveAiSetupParts(requestedPartNames, { exec });
557
+ return exec ? renderAiSetupCommands(parts) : renderPartialAiSetupPrompt(parts);
558
+ }
559
+
560
+ const AI_SETUP_PROMPT = renderAiSetupPrompt();
561
+ const AI_SETUP_COMMANDS = renderAiSetupPrompt({ exec: true });
415
562
 
416
563
  const SCORECARD_RISK_BY_CHECK = {
417
564
  'Dangerous-Workflow': 'Critical',
@@ -511,6 +658,9 @@ module.exports = {
511
658
  envFlagIsTruthy,
512
659
  isClaudeCodeSession,
513
660
  defaultAgentWorktreeRelativeDir,
661
+ listAiSetupPartNames,
662
+ parseAiSetupPartNames,
663
+ renderAiSetupPrompt,
514
664
  AI_SETUP_PROMPT,
515
665
  AI_SETUP_COMMANDS,
516
666
  SCORECARD_RISK_BY_CHECK,