Add Pandora Promotion Request Board v1#138
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Warning Review limit reached
Next review available in: 5 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (30)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5f2bfbb6b8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| export type OperatorActionDbClient = { from: (table: string) => any }; | ||
|
|
||
| const ACTIONS = new Set<OperatorActionType>(["verify_namespace_invariants", "verify_pack_supersession", "check_retrieval_eval_status", "refresh_dashboard_snapshot", "prepare_distill_smoke_plan", "prepare_shadow_context_pack", "prepare_shadow_pack_preflight"]); | ||
| const ACTIONS = new Set<OperatorActionType>(["verify_namespace_invariants", "verify_pack_supersession", "check_retrieval_eval_status", "refresh_dashboard_snapshot", "prepare_distill_smoke_plan", "prepare_shadow_context_pack", "prepare_shadow_pack_preflight", "prepare_promotion_request"]); |
There was a problem hiding this comment.
Add DB constraint support for promotion actions
When prepare_promotion_request is accepted here, proposeOperatorAction can now try to insert that value into pandora_operator_actions.action_type, but the migrations in this repo leave pandora_operator_actions_action_type_check without this new enum value. In deployed databases, selecting this new action through the composer or API will pass the service guard and then fail at insert with a check-constraint violation, so the operator-action path for promotion requests is unusable until the migration updates the constraint.
Useful? React with 👍 / 👎.
| const rollback_plan={ plan_version:"promotion_request_board_v1", rollback_available_after_future_promotion:true, steps:["identify newly promoted master","archive newly promoted master","restore previous active master","write rollback audit event","re-run verification"], rollback_execution_available:false }; | ||
| return { preflight, shadow, currentMaster, status, blockers, warnings:Array.from(new Set(warnings)), promotion_plan, rollback_plan, risk_snapshot:risk, diff_snapshot:preflight.diff_summary, request_id:input.requestId??randomUUID(), title:`Promotion request for ${preflight.namespace} shadow pack`, summary:`Human-approved promotion request only for shadow pack ${shadow.id}. Approval does not execute promotion.` }; | ||
| } | ||
| export async function createOrRefreshPromotionRequest(client:PromotionRequestDbClient,input:{userId:string; preflightId:string; requestId?:string}):Promise<PromotionRequestRow>{ const built=await buildPromotionRequestPlan(client,input); const existing=await getPromotionRequestByPreflight(client,{userId:input.userId,preflightId:input.preflightId}); const now=new Date().toISOString(); const base={user_id:input.userId,request_id:existing?.request_id??built.request_id,namespace:built.preflight.namespace,shadow_pack_id:built.shadow.id,preflight_id:built.preflight.id,active_master_pack_id:built.preflight.active_master_pack_id,status:built.status,title:built.title,summary:built.summary,promotion_plan:built.promotion_plan,rollback_plan:built.rollback_plan,risk_snapshot:built.risk_snapshot,diff_snapshot:built.diff_snapshot,warnings:built.warnings,updated_at:now}; const row=existing?await single(client.from("pandora_promotion_requests").update(base).eq("user_id",input.userId).eq("id",existing.id).select("*").single()):await single(client.from("pandora_promotion_requests").insert({id:randomUUID(),...base,reviewer_notes:"",reviewer_decision:null,created_at:now,submitted_at:null,approved_at:null,blocked_at:built.status==="blocked"?now:null,archived_at:null}).select("*").single()); if(!row) throw new Error("Unable to create or refresh promotion request"); await createPromotionRequestEvent(client,{userId:input.userId,promotionRequestId:row.id,shadowPackId:built.shadow.id,preflightId:built.preflight.id,eventType:existing?"promotion_request_refreshed":"promotion_request_created",message:"Promotion request prepared only; no promotion or core memory mutation performed.",metadata:{blockers:built.blockers,promotion_execution_available:false,no_core_memory_mutation_performed:true,no_promotion_performed:true}}); return row; } |
There was a problem hiding this comment.
Preserve reviewed promotion request status on refresh
When an existing request is refreshed from the preflight button or prepare_promotion_request execution, this update always writes status: built.status, which is either draft or blocked. That means refreshing an already submitted, approved, or archived request silently reopens or overwrites its review state while leaving the old reviewer fields/timestamps behind, corrupting the human-approval audit trail for any preflight that is refreshed after review.
Useful? React with 👍 / 👎.
| export async function getPromotionRequest(client:PromotionRequestDbClient,input:{userId:string; promotionRequestId:string}):Promise<PromotionRequestRow>{ const row=await single(client.from("pandora_promotion_requests").select("*").eq("user_id",input.userId).eq("id",input.promotionRequestId).limit(1)); if(!row) throw new Error("Promotion request not found for current user"); return row; } | ||
| export async function getPromotionRequestByPreflight(client:PromotionRequestDbClient,input:{userId:string; preflightId:string}):Promise<PromotionRequestRow|null>{ return single(client.from("pandora_promotion_requests").select("*").eq("user_id",input.userId).eq("preflight_id",input.preflightId).limit(1)); } | ||
| export async function createPromotionRequestEvent(client:PromotionRequestDbClient,input:{userId:string; promotionRequestId:string; shadowPackId:string; preflightId:string; eventType:string; message:string; metadata?:Record<string,unknown>}):Promise<PromotionRequestEventRow|null>{ const row={id:randomUUID(),user_id:input.userId,promotion_request_id:input.promotionRequestId,shadow_pack_id:input.shadowPackId,preflight_id:input.preflightId,event_type:input.eventType,message:input.message,metadata:input.metadata??{},created_at:new Date().toISOString()}; return single(client.from("pandora_promotion_request_events").insert(row).select("*").single()); } | ||
| export async function buildPromotionRequestPlan(client:PromotionRequestDbClient,input:{userId:string; preflightId:string; requestId?:string}){ const preflight=await getShadowPackPreflight(client as any,{userId:input.userId,preflightId:input.preflightId}); assertNamespace(preflight.namespace); const shadow=await getShadowContextPack(client as any,{userId:input.userId,shadowPackId:preflight.shadow_pack_id}); if(shadow.id!==preflight.shadow_pack_id) throw new Error("Preflight shadow pack mismatch"); if(shadow.namespace!==preflight.namespace) throw new Error("Shadow pack and preflight namespace mismatch"); const currentMaster=await activeMaster(client,input.userId,preflight.namespace); if(currentMaster && currentMaster.namespace!==preflight.namespace) throw new Error("Active master namespace mismatch"); const risk=preflight.risk_summary ?? { status:"blocked", blockers:["risk summary unavailable"], warnings:[]}; const warnings=[...(Array.isArray(preflight.warnings)?preflight.warnings:[]),...(Array.isArray((risk as any).warnings)?(risk as any).warnings:[])]; const blockers:string[]=[]; if(preflight.status!=="approved_for_promotion") blockers.push("Preflight is not approved_for_promotion."); if((risk as any).status==="blocked") blockers.push("Preflight risk status is blocked."); if(!currentMaster && (risk as any).status==="blocked") blockers.push("Active master is missing while risk status is blocked."); if((risk as any).status==="high") warnings.push("Risk status is high; human review should be cautious."); if(["rejected","archived"].includes(String(shadow.status))) warnings.push(`Shadow pack status is ${shadow.status}; promotion execution remains unavailable.`); if(new Date(preflight.updated_at).getTime() < new Date(shadow.updated_at).getTime()) warnings.push("Preflight is older than the shadow pack update timestamp."); if((preflight.active_master_pack_id??null)!==(currentMaster?.id??null)) warnings.push("Active master id in preflight no longer matches current active master id."); const status:PromotionRequestStatus=blockers.length?"blocked":"draft"; const promotion_plan={ plan_version:"promotion_request_board_v1", namespace:preflight.namespace, shadow_pack_id:shadow.id, preflight_id:preflight.id, active_master_pack_id:preflight.active_master_pack_id, intended_operation:"replace_active_master_with_shadow_candidate", steps:["verify preflight is approved_for_promotion","verify active master still matches preflight active_master_pack_id","verify shadow pack still reviewed or ready_for_review","archive existing active master","create new active master from shadow candidate","write audit event","refresh dashboard verification"], required_checks:["same_user","same_namespace","preflight_approved","risk_not_blocked","active_master_unchanged","no_duplicate_active_master_after_promotion"], execution_available:false, blockers }; |
There was a problem hiding this comment.
Block stale active-master promotion plans
If the active master changes or disappears after the preflight was approved, this only adds a warning, but submitPromotionRequest and approval only reject built.blockers. In that scenario the board can still mark a request approved with a promotion_plan.active_master_pack_id that no longer matches the current master, even though the plan lists active_master_unchanged as a required check; stale preflight/master mismatches should be blockers before submit or approval.
Useful? React with 👍 / 👎.
Motivation
Description
supabase/migrations/20260704020000_pandora_promotion_request_board.sqlthat createspandora_promotion_requestsandpandora_promotion_request_eventswith RLS policies, indexes,updated_attrigger, andunique(user_id, preflight_id).lib/services/pandora-promotion-request-service.tswhich builds deterministicpromotion_planandrollback_plan, enforces namespace/user/preflight/shadow ownership, computes blockers/warnings, and exposes CRUD and event APIs (list,get,getByPreflight,createOrRefresh,submit,updateReview,archive,createEvent).prepare_promotion_requestinlib/services/pandora-operator-action-service.tsso dry-runs compute plan snapshots only and approved execution creates/refreshes promotion request rows without performing promotions or core memory mutations.app/api/pandora/promotion-requests/*andapp/api/pandora/shadow-pack-preflights/[id]/promotion-requestthat require server-derived sessions and rejectuser_idoverrides./pandoradashboard and preflight list while clearly showing the banner "Promotion request only — execution unavailable".components/pandora/types.ts), docs (docs/pandora-promotion-request-board.mdand related updates), and safety guard tests to reflect the new board while maintaining the non-execution boundary.Testing
npm run typecheckand TypeScript checks passed with no blocking errors.npm run lintwhich completed and reported only existing non-blocking warnings in unrelated files.npm run testand unit suite completed successfully (99 test files, 635 tests passed).npm run buildwhich finished successfully with existing Next/Supabase runtime warnings only.npm run env:policywhich passed for discovered env keys.tests/unit/pandora-promotion-request-service.test.tsand updated guard tests to assert safety boundaries, and the new tests passed as part of the full test run.Codex Task