()
| 51 | } |
| 52 | |
| 53 | function main() { |
| 54 | if (hasFlag('--help') || hasFlag('-h')) { |
| 55 | process.stdout.write(`${usage()}\n`); |
| 56 | return; |
| 57 | } |
| 58 | |
| 59 | const projectRoot = path.resolve(arg('--project-root', process.cwd())); |
| 60 | const action = arg('--action'); |
| 61 | const verify = arg('--verify'); |
| 62 | const maxAttempts = Number(arg('--max-attempts', 3)); |
| 63 | const write = hasFlag('--write') || hasFlag('--run'); |
| 64 | |
| 65 | if (!verify) { |
| 66 | process.stderr.write('Missing --verify. A bounded loop needs a verifier.\n'); |
| 67 | process.exit(1); |
| 68 | } |
| 69 | if (!Number.isFinite(maxAttempts) || maxAttempts < 1) { |
| 70 | process.stderr.write('--max-attempts must be >= 1.\n'); |
| 71 | process.exit(1); |
| 72 | } |
| 73 | |
| 74 | const contractPlan = createLoopContract({ |
| 75 | type: 'foreground-loop', |
| 76 | title: arg('--title') || action || verify, |
| 77 | goal: arg('--goal') || action || verify, |
| 78 | command: action || null, |
| 79 | verifierCommand: verify, |
| 80 | maxAttempts, |
| 81 | triggerKind: 'manual', |
| 82 | status: write ? 'running' : 'planned', |
| 83 | }); |
| 84 | |
| 85 | if (!write) { |
| 86 | process.stdout.write(`Loop planned: ${contractPlan.id}\n`); |
| 87 | process.stdout.write(`State: ${contractPlan.statePath}\n`); |
| 88 | process.stdout.write('Pass --write or --run to execute.\n'); |
| 89 | return; |
| 90 | } |
| 91 | |
| 92 | const contract = registerLoop(projectRoot, contractPlan); |
| 93 | |
| 94 | let finalStatus = 'attempt-limit'; |
| 95 | for (let attempt = 1; attempt <= maxAttempts; attempt++) { |
| 96 | if (action) { |
| 97 | const actionResult = runShell(action, projectRoot); |
| 98 | appendLoopRun(projectRoot, contract.id, { |
| 99 | attempt, |
| 100 | status: actionResult.exitCode === 0 ? 'running' : 'blocked', |
| 101 | summary: actionResult.exitCode === 0 ? 'action completed' : 'action failed', |
| 102 | command: action, |
| 103 | exitCode: actionResult.exitCode, |
| 104 | startedAt: actionResult.startedAt, |
| 105 | completedAt: actionResult.completedAt, |
| 106 | }); |
| 107 | if (actionResult.exitCode !== 0) { |
| 108 | finalStatus = 'blocked'; |
| 109 | break; |
| 110 | } |
no test coverage detected