/** * Paused teams — the in-memory index every automation path consults * (specs/2026-10-04-team-pause.md). * * The pause itself is stored on the team (`Team.paused`, persisted in the * team's config.json), so it survives restarts. This module keeps a * synchronous index of it — team id → pause, and every session name a * member of a paused team may run under → team — because most of the gates * (the reconciler's wake rule, the queued-message wake, the dispatcher's * target planning) only have a session name and must not await storage. * * The index is rebuilt from storage: {@link syncPausedTeams} runs on every * `StorageService.getTeams()` read and at boot, and {@link notePausedTeam} * on every save. A pause whose `until` has passed counts as resumed at once, * before the auto-resume sweep clears it from storage. * * Module-level and dependency-free (types and two utils only), so the team * controller, the storage service and the services can share it without * import cycles. * * @module services/team/team-pause.registry */ import type { Team, TeamMember, TeamPauseState } from '../../types/index.js'; /** What the gates need to know about a paused team. */ export interface PausedTeamInfo { teamId: string; teamName: string; /** GitHub repository for issues while paused (`owner/name`), when configured */ issueRepo?: string; pause: TeamPauseState; /** Every session name a member may run under (session, agent id, derived name) */ sessions: string[]; /** Member display names */ memberNames: string[]; } /** * Whether a pause is in force at `now` (set, and its `until` not reached). * * @param pause - The team's pause, if any * @param now - Clock (ms) * @returns True while paused * * @example * isPauseActive({ pausedAt: '…', by: 'owner', until: '2099-01-01T00:00:00Z' }) // true */ export declare function isPauseActive(pause: TeamPauseState | null | undefined, now?: number): boolean; /** * Whether a team object is paused now. Prefer this where the team is at * hand: it reads the team itself, not the index. * * @param team - Team (only `paused` is read) * @param now - Clock (ms) * @returns True while paused */ export declare function isTeamPausedNow(team: Pick | null | undefined, now?: number): boolean; /** * Every session name a member may run under: its live session, its * permanent agent id, and the name the controller derives on start. * * @param teamName - Team display name * @param member - Member * @returns Distinct, non-empty session names */ export declare function memberSessionKeys(teamName: string, member: Pick): string[]; /** * Update the index for one team (after a save). A team that is not paused * is removed from it. * * @param team - The saved team */ export declare function notePausedTeam(team: Team | null | undefined): void; /** * Forget a deleted team. * * @param teamId - Deleted team */ export declare function noteTeamDeleted(teamId: string): void; /** * Every team the index has seen (id and name), archived ones excluded. * * @returns Teams */ export declare function listKnownTeams(): Array<{ id: string; name: string; }>; /** * Rebuild the index from a full team list (a storage read, boot). * * @param teams - Every stored team */ export declare function syncPausedTeams(teams: readonly Team[]): void; /** * The paused team with this id, if its pause is in force. * * @param teamId - Team id * @param now - Clock (ms) * @returns Info, or null */ export declare function pausedTeamById(teamId: string | null | undefined, now?: number): PausedTeamInfo | null; /** * Whether the team with this id is paused now. * * @param teamId - Team id * @returns True while paused */ export declare function isTeamIdPaused(teamId: string | null | undefined): boolean; /** * The paused team a session belongs to, if its pause is in force. * * @param session - Agent session (or agent id) * @param now - Clock (ms) * @returns Info, or null */ export declare function pausedTeamOfSession(session: string | null | undefined, now?: number): PausedTeamInfo | null; /** * Whether a session belongs to a paused team. * * @param session - Agent session (or agent id) * @returns True while its team is paused * * @example * if (isSessionPaused(wi.target)) return false; // do not dispatch */ export declare function isSessionPaused(session: string | null | undefined): boolean; /** * The paused team named by an id, a name (case-insensitive) or a member * session — whatever an agent typed. * * @param ref - Team id, team name, or member session * @returns Info, or null */ export declare function pausedTeamByRef(ref: string | null | undefined): PausedTeamInfo | null; /** * Every team paused now. * * @param now - Clock (ms) * @returns Infos */ export declare function listPausedTeams(now?: number): PausedTeamInfo[]; /** * Teams whose pause has an `until` that has passed (still stored as paused). * * @param now - Clock (ms) * @returns Infos due for auto-resume */ export declare function listExpiredPauses(now?: number): PausedTeamInfo[]; /** * The refusal an agent gets when it targets a paused team (English: harness * text rule). * * @param info - The paused team * @param options - `callerIsOrc`: the orchestrator asked (it tells the owner, not itself) * @returns Message * * @example * pausedRefusalMessage({ teamName: 'Crewly', issueRepo: 'stevehuang0115/crewly' }) * // 'Crewly is paused by the owner. File a GitHub issue instead: `gh issue create -R stevehuang0115/crewly --title "…" --body "…"`' */ export declare function pausedRefusalMessage(info: Pick & { pause?: TeamPauseState; }, options?: { callerIsOrc?: boolean; }): string; /** Clear the index (tests only). */ export declare function resetTeamPauseRegistryForTesting(): void; //# sourceMappingURL=team-pause.registry.d.ts.map