diff --git a/client/src/hooks/use-consilium-loops.ts b/client/src/hooks/use-consilium-loops.ts index 12a9a40..bfd68df 100644 --- a/client/src/hooks/use-consilium-loops.ts +++ b/client/src/hooks/use-consilium-loops.ts @@ -518,9 +518,9 @@ export function useApproveMerge() { */ export function useDevelopLoop() { const qc = useQueryClient(); - return useMutation({ - // MR-size control: `scope: "p0"` develops only the P0s (small reviewable MR); - // omitted/"all" keeps the historical full-verdict round. + return useMutation({ + // MR-size control: `scope: "top"` develops only the highest remaining priority + // tier (small reviewable MR); omitted/"all" keeps the historical full round. mutationFn: ({ id, scope }) => apiRequest("POST", `${LIST_KEY}/${id}/develop`, scope ? { scope } : undefined), onSuccess: (_data, { id }) => { diff --git a/client/src/pages/ConsiliumLoopDetail.tsx b/client/src/pages/ConsiliumLoopDetail.tsx index 826dedd..8221652 100644 --- a/client/src/pages/ConsiliumLoopDetail.tsx +++ b/client/src/pages/ConsiliumLoopDetail.tsx @@ -2806,11 +2806,18 @@ export default function ConsiliumLoopDetail() { const latestActionPointCount = Array.isArray(latestRound?.openActionPoints) ? latestRound!.openActionPoints.length : 0; - // MR-size control: P0 slice of the latest verdict — offered as a smaller round. - const latestP0Count = Array.isArray(latestRound?.openActionPoints) - ? (latestRound!.openActionPoints as ActionPoint[]).filter((ap) => ap.priority === "P0") - .length - : 0; + // MR-size control (ADR-005 Phase 1): the HIGHEST priority tier still present in + // the latest verdict — offered as a smaller round (mirrors server filterDevScope). + const latestAps: ActionPoint[] = Array.isArray(latestRound?.openActionPoints) + ? (latestRound!.openActionPoints as ActionPoint[]) + : []; + const tierRankOf = (p?: string): number => + ({ P0: 0, P1: 1, P2: 2, P3: 3 } as Record)[p ?? ""] ?? 4; + const topTierRank = latestAps.length + ? Math.min(...latestAps.map((ap) => tierRankOf(ap.priority))) + : 4; + const topTierLabel = ["P0", "P1", "P2", "P3", "unprioritized"][topTierRank]; + const topTierCount = latestAps.filter((ap) => tierRankOf(ap.priority) === topTierRank).length; const canDevelop = isVerdictTerminalLoopState(loop.state) && latestActionPointCount > 0; @@ -2887,7 +2894,8 @@ export default function ConsiliumLoopDetail() { async function handleDevelop(scopeArg?: unknown) { // Normalize: plain onClick callers pass a click event — only the two literal // scopes ride to the server; anything else means "all" (historical behaviour). - const scope = scopeArg === "p0" || scopeArg === "all" ? scopeArg : undefined; + const scope = + scopeArg === "p0" || scopeArg === "top" || scopeArg === "all" ? scopeArg : undefined; setDevelopScopeOpen(false); try { await developLoop.mutateAsync({ id, scope }); @@ -2965,9 +2973,9 @@ export default function ConsiliumLoopDetail() {