ralph-prd 1.0.6 → 1.0.8

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/README.md CHANGED
@@ -93,8 +93,10 @@ Options:
93
93
  --only-phase N Force re-run phase N (1-based)
94
94
  --i-did-this Skip Claude self-commit; run separate commit step
95
95
  --send-it Push branch + open PR when all phases complete
96
- --wait-for-it Pause before each commit for review
97
- --update-skills Re-fetch skills from tahaJemmali/skills and exit
96
+ --wait-for-it Pause before each commit for review
97
+ --skip-ship-check Skip the post-commit ship-check step
98
+ --skip-on-verify-fail Skip verification and continue instead of hard-stopping when all repair attempts fail
99
+ --update-skills Re-fetch skills from tahaJemmali/skills and exit
98
100
  --version, -v Print installed version and exit
99
101
  ```
100
102
 
@@ -145,6 +147,7 @@ writableDirs:
145
147
  flags:
146
148
  maxRepairs: 3
147
149
  sendIt: false
150
+ skipOnVerifyFail: false
148
151
 
149
152
  hooks:
150
153
  afterCommit: npm test
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ralph-prd",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "description": "AI-powered phased implementation runner for Claude Code — from PRD to shipped code",
5
5
  "bin": {
6
6
  "ralph-prd": "./bin/install.mjs"
@@ -29,7 +29,8 @@ function isGitRepo(dirPath) {
29
29
  * @property {number} maxRepairs - Max repair attempts per phase before hard-stopping (default 3)
30
30
  * @property {number|null} onlyPhase - When set, only this 1-based phase index is run (force re-run)
31
31
  * @property {string} logLevel - "none" | "necessary" | "dump" (default "necessary")
32
- * @property {boolean} skipShipCheck - Skip the post-commit ship-check step for every phase
32
+ * @property {boolean} skipShipCheck - Skip the post-commit ship-check step for every phase
33
+ * @property {boolean} skipOnVerifyFail - Skip verification and continue instead of hard-stopping when all repair attempts fail
33
34
  */
34
35
 
35
36
  /**
@@ -60,7 +61,7 @@ function isGitRepo(dirPath) {
60
61
  function parseConfigYaml(content) {
61
62
  const repos = [];
62
63
  const writableDirs = [];
63
- const flags = { iDidThis: false, sendIt: false, waitForIt: false, maxRepairs: 3, onlyPhase: null, logLevel: 'necessary', skipShipCheck: false };
64
+ const flags = { iDidThis: false, sendIt: false, waitForIt: false, maxRepairs: 3, onlyPhase: null, logLevel: 'necessary', skipShipCheck: false, skipOnVerifyFail: false };
64
65
  const hooks = { afterCommit: null };
65
66
  let section = null;
66
67
  let current = null;
@@ -160,7 +161,7 @@ function parseConfigYaml(content) {
160
161
  */
161
162
  export function resolveRepos(runnerDir) {
162
163
  const configPath = join(runnerDir, CONFIG_FILENAME);
163
- const defaultFlags = { iDidThis: false, sendIt: false, waitForIt: false, maxRepairs: 3, onlyPhase: null, skipShipCheck: false };
164
+ const defaultFlags = { iDidThis: false, sendIt: false, waitForIt: false, maxRepairs: 3, onlyPhase: null, skipShipCheck: false, skipOnVerifyFail: false };
164
165
  const defaultHooks = { afterCommit: null };
165
166
 
166
167
  if (!existsSync(configPath)) {
@@ -134,6 +134,8 @@ const sendItArg = args.includes('--send-it');
134
134
  const waitForItArg = args.includes('--wait-for-it');
135
135
  // Skip the post-commit ship-check step. Use when you don't have a ship-check skill.
136
136
  const skipShipCheckArg = args.includes('--skip-ship-check');
137
+ // Skip verification and continue (rather than hard-stop) when all repair attempts fail.
138
+ const skipOnVerifyFailArg = args.includes('--skip-on-verify-fail');
137
139
  // Run only one specific phase (1-based), force re-run even if already complete.
138
140
  const onlyPhaseArg = (() => {
139
141
  const idx = args.indexOf('--only-phase');
@@ -154,7 +156,7 @@ const logLevelArg = (() => {
154
156
  if (!planArg) {
155
157
  console.error(
156
158
  'Usage: node ralph-claude.mjs <plan-file.md> ' +
157
- '[--reset|--dry-run|--i-did-this|--send-it|--wait-for-it|--skip-ship-check|--only-phase N|--log-level none|necessary|dump|--update-skills|--version]'
159
+ '[--reset|--dry-run|--i-did-this|--send-it|--wait-for-it|--skip-ship-check|--skip-on-verify-fail|--only-phase N|--log-level none|necessary|dump|--update-skills|--version]'
158
160
  );
159
161
  process.exit(1);
160
162
  }
@@ -349,6 +351,7 @@ async function main() {
349
351
  const sendIt = sendItArg || configFlags.sendIt;
350
352
  const waitForIt = waitForItArg || configFlags.waitForIt;
351
353
  const skipShipCheck = skipShipCheckArg || configFlags.skipShipCheck;
354
+ const skipOnVerifyFail = skipOnVerifyFailArg || configFlags.skipOnVerifyFail;
352
355
  const onlyPhase = onlyPhaseArg ?? configFlags.onlyPhase ?? null;
353
356
  const logLevel = logLevelArg ?? configFlags.logLevel ?? 'necessary';
354
357
 
@@ -574,19 +577,26 @@ async function main() {
574
577
  }));
575
578
  console.log('ok');
576
579
  } catch (err) {
577
- console.log('failed');
578
- let errMsg;
579
- if (err instanceof VerificationError) {
580
- errMsg = `Verification failed for phase "${err.phaseName}"`;
581
- console.error(`\n${errMsg}:`);
580
+ if (err instanceof VerificationError && skipOnVerifyFail) {
581
+ console.log(`skipped (failed ${configFlags.maxRepairs} time${configFlags.maxRepairs === 1 ? '' : 's'})`);
582
+ console.error(`\nVerification for "${err.phaseName}" failed ${configFlags.maxRepairs} time${configFlags.maxRepairs === 1 ? '' : 's'} — skipping to avoid token waste.`);
582
583
  if (err.failureNotes) console.error(err.failureNotes);
584
+ console.error(`Logs: ${logsDir}`);
583
585
  } else {
584
- errMsg = `Unexpected error during verification: ${err.message}`;
585
- console.error(`\n${errMsg}`);
586
+ console.log('failed');
587
+ let errMsg;
588
+ if (err instanceof VerificationError) {
589
+ errMsg = `Verification failed for phase "${err.phaseName}"`;
590
+ console.error(`\n${errMsg}:`);
591
+ if (err.failureNotes) console.error(err.failureNotes);
592
+ } else {
593
+ errMsg = `Unexpected error during verification: ${err.message}`;
594
+ console.error(`\n${errMsg}`);
595
+ }
596
+ console.error(`Logs: ${logsDir}`);
597
+ notify('Ralph — failed', errMsg);
598
+ process.exit(1);
586
599
  }
587
- console.error(`Logs: ${logsDir}`);
588
- notify('Ralph — failed', errMsg);
589
- process.exit(1);
590
600
  }
591
601
 
592
602
  // Checkpoint: verification done
@@ -710,6 +720,34 @@ async function main() {
710
720
  }));
711
721
  const dur = ((Date.now() - shipCheckStart) / 1000).toFixed(1);
712
722
  console.log(`VERDICT: APPROVED (${dur}s)`);
723
+
724
+ // Ship-check repair may have modified files — commit any leftovers.
725
+ const postShipChanges = await scanChangedRepos(repos);
726
+ if (postShipChanges.length > 0) {
727
+ process.stdout.write(` [${ts()}] post-ship-check commit… `);
728
+ try {
729
+ const { nextTaskNum, anyCommitted } = await runCommitStep({
730
+ phase,
731
+ repos,
732
+ safetyHeader,
733
+ logWriter,
734
+ phaseNum,
735
+ taskNum,
736
+ send,
737
+ });
738
+ taskNum = nextTaskNum;
739
+ console.log(anyCommitted ? 'ok' : 'skipped (no changes)');
740
+ } catch (err) {
741
+ console.log('failed');
742
+ const msg = err instanceof CommitError
743
+ ? `Phase "${err.phaseName}" post-ship-check commit failed: ${err.message}`
744
+ : `Unexpected error during post-ship-check commit: ${err.message}`;
745
+ console.error(`\n${msg}`);
746
+ console.error(`Logs: ${logsDir}`);
747
+ notify('Ralph — failed', msg);
748
+ process.exit(1);
749
+ }
750
+ }
713
751
  } catch (err) {
714
752
  const dur = ((Date.now() - shipCheckStart) / 1000).toFixed(1);
715
753
  if (err instanceof ShipCheckError) {
@@ -53,3 +53,10 @@ flags:
53
53
  # have not installed a ship-check skill or want to disable the review gate.
54
54
  # CLI equivalent: --skip-ship-check
55
55
  skipShipCheck: false
56
+
57
+ # When all repair attempts are exhausted, skip verification and continue to
58
+ # the commit step instead of hard-stopping. Useful when the acceptance
59
+ # criteria require external credentials or manual steps that the agent cannot
60
+ # perform. Defaults to false (hard stop).
61
+ # CLI equivalent: --skip-on-verify-fail
62
+ skipOnVerifyFail: false