/** * Ticket → Slack thread map (specs/2026-10-01-decision-cards.md §2, §6). * * Each project ticket gets ONE Slack thread in its team channel: the first * decision card (or the first top-level post about it) becomes the thread * root, and every later card, answer and update for that ticket goes into * that thread. Stored under CREWLY_HOME (not in the project), keyed by the * project path and ticket id. * * @module services/decisions/ticket-thread-store */ /** One ticket's thread. */ export interface TicketThread { slackChannelId: string; threadTs: string; teamId?: string; createdAt: string; } /** * The key of a ticket. * * @param projectPath - Absolute project root * @param ticketId - Ticket id (`APP-12`) * @returns `#` */ export declare function ticketThreadKey(projectPath: string, ticketId: string): string; /** * Persistent ticket → Slack thread map. All writes are serialised. */ export declare class TicketThreadStore { private readonly filePath; private data; private chain; /** * @param filePath - JSON file (default: `/ticket-slack-threads.json`) */ constructor(filePath: string); /** * Store under a CREWLY_HOME. * * @param crewlyHome - CREWLY_HOME * @returns The store */ static inHome(crewlyHome: string): TicketThreadStore; /** * The ticket's thread, when it has one. * * @param projectPath - Project root * @param ticketId - Ticket id * @returns The thread, or null */ get(projectPath: string, ticketId: string): Promise; /** * Record the ticket's thread. An existing thread is kept (first one wins). * * @param projectPath - Project root * @param ticketId - Ticket id * @param thread - Channel + root ts (+ team) * @returns The thread now on record */ set(projectPath: string, ticketId: string, thread: Omit): Promise; /** * Find the ticket a Slack thread belongs to. * * @param slackChannelId - Channel * @param threadTs - Thread root ts * @returns `{ projectPath, ticketId }`, or null */ findByThread(slackChannelId: string, threadTs: string): Promise<{ projectPath: string; ticketId: string; } | null>; private load; private serial; } /** * Install the process-wide store (composition root / tests). * * @param store - Store or null */ export declare function setTicketThreadStore(store: TicketThreadStore | null): void; /** * The process-wide store, or null before wiring. * * @returns Store or null */ export declare function getTicketThreadStore(): TicketThreadStore | null; /** * A link to a Slack message that opens in the owner's workspace * (`https://slack.com/archives//p`). * * @param slackChannelId - Channel * @param ts - Message ts * @returns URL */ export declare function slackArchiveLink(slackChannelId: string, ts: string): string; //# sourceMappingURL=ticket-thread-store.d.ts.map