(input: PromotionInput)
| 32 | } |
| 33 | |
| 34 | export function decidePromotion(input: PromotionInput): PromotionDecision { |
| 35 | const { authorModel, verdict, activeSameName } = input; |
| 36 | |
| 37 | // 1 + 2: independent, passing judge — no self-grade, no fallback. |
| 38 | if (!verdict) { |
| 39 | return { promote: false, reason: 'no independent judge verdict — candidate stays quarantined (self-grade is never accepted)' }; |
| 40 | } |
| 41 | if (!verdict.judgeModel || verdict.judgeModel === authorModel) { |
| 42 | return { promote: false, reason: `judge model (${verdict.judgeModel || 'unknown'}) is the same as the author model — self-grade rejected; configure a separate reflection model` }; |
| 43 | } |
| 44 | if (!verdict.pass) { |
| 45 | return { promote: false, reason: `independent judge rejected the candidate: ${verdict.reasons.join('; ') || 'no reason given'}` }; |
| 46 | } |
| 47 | |
| 48 | // 3: never overwrite a human-authored/edited skill. |
| 49 | if (activeSameName && isProtected(activeSameName)) { |
| 50 | return { promote: false, reason: 'an active human-authored skill of the same name exists — refusing to overwrite it; keep this as a candidate or rename it' }; |
| 51 | } |
| 52 | |
| 53 | return { promote: true, reason: `independent judge (${verdict.judgeModel}) passed it and no protected skill blocks the name` }; |
| 54 | } |
no test coverage detected