(options = {})
| 384 | const hint = String(authorHint || 'codex').toLowerCase(); |
| 385 | return author.includes(hint) || body.includes('@codex') || body.includes('codex review'); |
| 386 | } |
| 387 | |
| 388 | function severityForBody(body) { |
| 389 | const match = String(body || '').match(/\b(P0|P1|P2|P3)\b/i); |
| 390 | return match ? match[1].toUpperCase() : null; |
| 391 | } |
| 392 | |
| 393 | function ingestCodexReview(options = {}) { |
| 394 | const projectRoot = path.resolve(options.projectRoot || process.cwd()); |
| 395 | const repo = options.repo || 'current-repo'; |
| 396 | const prNumber = options.prNumber || options.pr || 'current'; |
| 397 | const authorHint = options.authorHint || 'codex'; |
| 398 | const raw = typeof options.input === 'string' ? JSON.parse(options.input) : (options.input || []); |
| 399 | const allItems = normalizeReviewItems(raw); |
| 400 | const findings = allItems |
| 401 | .filter((item) => looksLikeCodexReviewItem(item, authorHint)) |
| 402 | .map((item) => { |
| 403 | const body = itemBody(item); |
| 404 | return { |
| 405 | id: item.id || item.node_id || null, |
| 406 | source: item.source || item.type || 'github-review', |
| 407 | author: itemAuthor(item), |
| 408 | severity: severityForBody(body), |
| 409 | path: item.path || null, |
| 410 | line: item.line || item.original_line || null, |
| 411 | url: item.html_url || item.url || null, |
| 412 | body, |
| 413 | }; |
| 414 | }); |
| 415 | |
| 416 | const counts = findings.reduce((acc, finding) => { |
| 417 | const key = finding.severity || 'unclassified'; |
| 418 | acc[key] = (acc[key] || 0) + 1; |
| 419 | return acc; |
| 420 | }, {}); |
| 421 | |
| 422 | const nextActions = []; |
| 423 | if ((counts.P0 || 0) + (counts.P1 || 0) > 0) { |
| 424 | nextActions.push('Run local Citadel verification before merge.'); |
| 425 | nextActions.push(`Consider commenting "@codex fix the P1/P0 issue" only after confirming the finding belongs.`); |
| 426 | } |
| 427 | if (findings.length === 0) { |
| 428 | nextActions.push('No Codex review findings were detected in the provided input.'); |
| 429 | } |
| 430 | |
| 431 | const result = { |
| 432 | repo, |
| 433 | prNumber, |
| 434 | source: 'codex-github-review', |
| 435 | ingestedAt: nowIso(options), |
| 436 | totalItems: allItems.length, |
| 437 | codexItems: findings.length, |
| 438 | counts, |
| 439 | findings, |
| 440 | nextActions, |
| 441 | }; |
| 442 | |
| 443 | if (options.write) { |
no test coverage detected