/** * Ticket claim policy — which queued WorkItem an agent takes next * (specs/ticket-loop.md, Phase 3). * * Pure functions over the pool and a snapshot of tickets, used by every * claim path (`claimFromPool`, `claimSpecificItem`, AutoClaim) so the order * and the lock are the same everywhere. * * **Order** (first tier wins, then oldest first): * 1. own rejected — rework / retry of this agent's work that was sent back * 2. own unblocked — this agent's work that was blocked and is free again * 3. queue rejected — rework / retry nobody owns yet * 4. everything else by priority: P0, P1, P2, P3 (ticket priority when the * item belongs to a ticket, else the item's own `metadata.priority`) * * **Lock — one ticket per agent.** * - An untargeted item of a ticket that already has an assignee is only for * that assignee (an explicit `target` still wins: a lead may hand one piece * of a ticket to someone else). * - An agent that still has open work on one ticket does not self-claim an * untargeted item of another ticket. Items targeted at it are never held * back — someone deliberately gave it that work. * * @module services/task-pool/ticket-claim-policy */ import type { WorkItem } from '../../types/v2/work-item.types.js'; import type { RequestPriority } from '../../types/v2/request.types.js'; /** What the policy needs to know about a ticket. */ export interface ClaimTicketView { id: string; priority: RequestPriority; /** Agent that owns the ticket, when any */ assignee?: string; } /** Tickets by Request id (non-ticket Requests are simply absent). */ export type ClaimTicketLookup = ReadonlyMap; /** Claim tiers, lowest first. */ export declare const CLAIM_TIER: { readonly OWN_REJECTED: 0; readonly OWN_UNBLOCKED: 1; readonly QUEUE_REJECTED: 2; /** P0 … P3 follow: PRIORITY_BASE + 0..3 */ readonly PRIORITY_BASE: 3; }; /** * Whether an item is a do-over of work that was sent back: a ticket rework * (打回 from the board) or a reviewer's retry. * * @param wi - WorkItem * @returns True for rework / retry items */ export declare function isReworkItem(wi: Pick): boolean; /** * The tier of an item for one agent (see module docs). * * @param wi - Candidate WorkItem * @param agentId - The claiming agent * @param tickets - Ticket snapshot * @returns Tier number (lower is taken first) */ export declare function claimTier(wi: WorkItem, agentId: string, tickets: ClaimTicketLookup): number; /** * Tickets an agent is still working on: any ticket with an open (queued, * running, blocked, rejected) item targeted at the agent. * * @param pool - Every WorkItem * @param agentId - The agent * @param tickets - Ticket snapshot * @returns Ticket ids */ export declare function openTicketsOf(pool: readonly WorkItem[], agentId: string, tickets: ClaimTicketLookup): Set; /** * Why an agent may not self-claim an item, or null when it may. * * @param wi - Candidate WorkItem * @param agentId - The claiming agent * @param tickets - Ticket snapshot * @param agentOpenTickets - {@link openTicketsOf} for this agent * @returns `'ticket_owned_by_other'`, `'agent_on_other_ticket'`, or null */ export declare function ticketLockReason(wi: WorkItem, agentId: string, tickets: ClaimTicketLookup, agentOpenTickets: ReadonlySet): 'ticket_owned_by_other' | 'agent_on_other_ticket' | null; /** * Candidates in the order an agent should take them, lock applied. * * @param candidates - Queued, unclaimed items the agent may take (target already respected) * @param agentId - The claiming agent * @param pool - Every WorkItem (for the lock) * @param tickets - Ticket snapshot * @returns Ordered, lock-filtered candidates */ export declare function orderForAgent(candidates: readonly WorkItem[], agentId: string, pool: readonly WorkItem[], tickets: ClaimTicketLookup): WorkItem[]; /** * Stable key of the project ticket (`.crewly/tickets/`) a WorkItem works on. * * @param wi - WorkItem * @returns `#`, or null when it is not ticket work */ export declare function projectTicketKey(wi: Pick): string | null; /** * Keep only the first project ticket's items in an ordered list, plus every * item that is not ticket work. Used for reminders listing an agent's queued * items: one ticket at a time (specs/ticket-loop.md), so the reminder must * not hand the agent several tickets to "work through in this turn" — it can * hold only one claim, and the unclaimed ones were then grace-revoked or * refused on completion (2026-09-29, CE-3 / CE-8 / CE-19 batched to Vera). * * @param ordered - Items in the order the agent should take them * @returns The items, with later tickets' items dropped (order preserved) */ export declare function limitToOneProjectTicket>(ordered: readonly T[]): T[]; //# sourceMappingURL=ticket-claim-policy.d.ts.map