(options = {})
| 140 | } |
| 141 | |
| 142 | function createPrReviewPlan(options = {}) { |
| 143 | const projectRoot = path.resolve(options.projectRoot || process.cwd()); |
| 144 | const prNumber = options.prNumber || options.pr || 'current'; |
| 145 | const repo = options.repo || 'current-repo'; |
| 146 | const risk = options.risk || 'medium'; |
| 147 | const changedFiles = Number(options.changedFiles || 0); |
| 148 | |
| 149 | let decision = 'codex-review'; |
| 150 | const reasons = ['Codex GitHub review is native and reads AGENTS.md review guidance.']; |
| 151 | if (risk === 'high' || changedFiles > 20) { |
| 152 | decision = 'combined'; |
| 153 | reasons.push('High-risk or large PRs still need Citadel local review and verification state.'); |
| 154 | } else if (risk === 'local-only') { |
| 155 | decision = 'local-review'; |
| 156 | reasons.push('The work depends on local state or unpushed changes Codex GitHub review cannot see.'); |
| 157 | } |
| 158 | |
| 159 | const plan = { |
| 160 | repo, |
| 161 | prNumber, |
| 162 | decision, |
| 163 | risk, |
| 164 | changedFiles, |
| 165 | command: decision === 'local-review' ? `/triage pr ${prNumber}` : '@codex review', |
| 166 | followUpPrompt: decision === 'combined' |
| 167 | ? `@codex review this PR. Focus on P0/P1 correctness and security issues. Citadel will also run local verification.` |
| 168 | : `@codex review this PR. Follow the AGENTS.md review guidelines and focus comments on actionable P0/P1 issues.`, |
| 169 | capturePath: path.join('.planning', 'pr-review', `${slugify(repo)}-${prNumber}.json`), |
| 170 | reasons, |
| 171 | improvesOnLocalOnly: [ |
| 172 | 'Uses Codex native PR review for GitHub-visible diffs.', |
| 173 | 'Keeps Citadel responsible for merge readiness, local verification, and follow-up state.', |
| 174 | ], |
| 175 | createdAt: nowIso(options), |
| 176 | }; |
| 177 | |
| 178 | if (options.write) { |
| 179 | writeJson(path.join(projectRoot, plan.capturePath), plan); |
| 180 | } |
| 181 | return plan; |
| 182 | } |
| 183 | |
| 184 | function recordPrReviewResult(options = {}) { |
| 185 | const projectRoot = path.resolve(options.projectRoot || process.cwd()); |
no test coverage detected