@smwb/onreel-git-mcp 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tracker/tracker.const.ts","../../src/tracker/tracker.lib.ts","../../src/tracker/mapping.const.ts","../../src/tracker/http.lib.ts","../../src/tracker/registry.lib.ts","../../src/tracker/github.lib.ts","../../src/tracker/gitlab.lib.ts","../../src/tracker/jira.lib.ts","../../src/tracker/local.lib.ts","../../src/tracker/sourcecraft.lib.ts","../../src/tracker/builtin.lib.ts","../../src/tracker/secrets.lib.ts"],"sourcesContent":["// Константы адаптеров трекеров библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/tracker.const.ts — дословная копия; фильтры и возможности списков — свои (#14).\nimport type { IssueCapabilities } from './tracker.types.ts';\n\n/** Потолок ожидания ответа внешнего трекера, мс. */\nexport const TRACKER_TIMEOUT_MS = 15_000;\n\n/** Размер страницы списка задач по умолчанию; потолок — 500 по контракту. */\nexport const TRACKER_PAGE_LIMIT_DEFAULT = 50;\n\n/** Сколько символов тела ответа трекера попадает в текст ошибки. */\nexport const TRACKER_ERROR_BODY_MAX = 300;\n\n/** Файл секретов подключений в каталоге данных host: токены трекеров по projectId, права 0600 (D-352). */\nexport const TRACKER_SECRETS_FILE = 'tracker-secrets.json';\n\n/** Автор комментариев, которые пользователь пишет в локальном трекере. */\nexport const TRACKER_LOCAL_AUTHOR = 'owner';\n\n/** Фильтры списка задач — имена полей IssueQuery; порядок — для текстов отказов. */\nexport const ISSUE_FILTERS = ['status', 'labels', 'assignee', 'author', 'search', 'createdAfter', 'createdBefore', 'updatedAfter', 'updatedBefore'] as const;\nexport type IssueFilter = (typeof ISSUE_FILTERS)[number];\n\n/** Поля сортировки задач единой модели. */\nexport const ISSUE_SORT_FIELDS = ['created', 'updated', 'priority', 'title', 'comments'] as const;\nexport type IssueSortField = (typeof ISSUE_SORT_FIELDS)[number];\n\n/** Фильтры списка комментариев — имена полей CommentQuery. */\nexport const COMMENT_FILTERS = ['updatedAfter'] as const;\nexport type CommentFilter = (typeof COMMENT_FILTERS)[number];\n\n/** Возможности трекера без раздела issues (свои трекеры потребителя): статус и страницы, комментарии по порядку. */\nexport const LEGACY_ISSUE_CAPABILITIES: IssueCapabilities = {\n list: { filters: ['status'], clientSide: ['status'], sorts: [] },\n comments: { filters: [], clientSide: [], order: ['asc'] },\n};\n","// Чистые помощники адаптеров трекеров библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/tracker.lib.ts — дословная копия, импорт типов из среза контракта библиотеки;\n// проверка запросов списков и помощники фильтров — свои (#14).\nimport type { IssuePriority, IssueStatusCategory } from '../contract/contract.types.ts';\nimport { COMMENT_FILTERS, LEGACY_ISSUE_CAPABILITIES } from './tracker.const.ts';\nimport type { CommentCapabilities, CommentQuery, IssueCapabilities, ListCapabilities, ListSort, TrackerDefinition, TrackerFailure } from './tracker.types.ts';\n\n/** Отказ адаптера: потребитель превращает его в ошибку своего контракта (D-353). */\nexport class TrackerError extends Error {\n readonly failure: TrackerFailure;\n constructor(failure: TrackerFailure, message: string) {\n super(message);\n this.name = 'TrackerError';\n this.failure = failure;\n }\n}\n\n/** Время трекера (ISO 8601) в миллисекунды; нет или не разобралось — undefined. */\nexport function toTimestamp(value: unknown): number | undefined {\n if (typeof value !== 'string') return undefined;\n const ms = Date.parse(value);\n return Number.isFinite(ms) && ms >= 0 ? ms : undefined;\n}\n\n/** Поле, которое задано: непустая строка. */\nexport function text(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nexport function clipText(value: string, max: number): string {\n return value.length <= max ? value : value.slice(0, max);\n}\n\n/** Строки из массива неизвестного вида: непустые строки без дублей. */\nexport function stringList(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return [...new Set(value.filter((item): item is string => typeof item === 'string' && item !== ''))];\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Категория и приоритет по таблице; нет в таблице — запасное значение. */\nexport function lookup<T>(table: Readonly<Record<string, T>>, key: unknown, fallback: T): T {\n return typeof key === 'string' && Object.hasOwn(table, key) ? (table[key] as T) : fallback;\n}\n\nexport function requireTarget(target: string | undefined, hint: string): string {\n if (target === undefined) throw new TrackerError('invalid_request', `Не задан target подключения: ${hint}.`);\n return target;\n}\n\n/** Обратная таблица: категория → первое имя статуса трекера. */\nexport function nameOf(table: Readonly<Record<string, IssueStatusCategory>>, category: IssueStatusCategory): string | undefined {\n return Object.entries(table).find(([, value]) => value === category)?.[0];\n}\n\nexport function priorityName(table: Readonly<Record<string, IssuePriority>>, priority: IssuePriority): string | undefined {\n return Object.entries(table).find(([, value]) => value === priority)?.[0];\n}\n\n/** Фильтры запроса со значением (не undefined и не пустой массив), в порядке names. */\nexport function usedFilters<F extends string>(query: Readonly<Partial<Record<F, unknown>>>, names: readonly F[]): F[] {\n return names.filter((name) => {\n const value = query[name];\n return value !== undefined && !(Array.isArray(value) && value.length === 0);\n });\n}\n\n/**\n * Проверка запроса списка по возможностям (D-004, R-002): фильтр со значением вне filters или sort.field вне sorts —\n * TrackerError('unsupported', `${subject}: фильтр ${name} не поддерживается.`); значение не той формы — invalid_request:\n * время не числом или не целое ≥ 0, пустая строка фильтра, список со строкой-пустышкой. subject — что за список:\n * 'Задачи GitHub', 'PR GitLab', 'Прогоны CI SourceCraft'.\n */\nexport function assertListQuery<F extends string, S extends string>(\n subject: string,\n capabilities: ListCapabilities<F, S>,\n query: Readonly<Partial<Record<F, unknown>>> & { readonly sort?: ListSort<S> | undefined },\n names: readonly F[],\n): void {\n const used = usedFilters(query, names);\n for (const name of used) {\n if (!capabilities.filters.includes(name)) throw new TrackerError('unsupported', `${subject}: фильтр ${name} не поддерживается.`);\n }\n const sort = query.sort;\n if (sort !== undefined && !capabilities.sorts.includes(sort.field)) {\n throw new TrackerError('unsupported', `${subject}: сортировка по ${sort.field} не поддерживается.`);\n }\n if (sort?.direction !== undefined && sort.direction !== 'asc' && sort.direction !== 'desc') {\n throw new TrackerError('invalid_request', `${subject}: направление сортировки — asc или desc.`);\n }\n // limit — поле PageQuery, а не фильтр: проверяется, когда запрос его несёт.\n const limit = (query as { readonly limit?: unknown }).limit;\n if (limit !== undefined && !(typeof limit === 'number' && Number.isSafeInteger(limit) && limit >= 1)) {\n throw new TrackerError('invalid_request', `${subject}: limit — целое число от 1.`);\n }\n for (const name of used) {\n const value = query[name];\n if (isTimeFilter(name)) {\n if (typeof value !== 'number' || !(Number.isSafeInteger(value) && value >= 0)) {\n throw new TrackerError('invalid_request', `${subject}: фильтр ${name} — время в мс, целое число от 0.`);\n }\n continue;\n }\n if (isArrayFilter(name)) {\n if (!Array.isArray(value) || value.some((item) => typeof item !== 'string' || item.trim() === '')) {\n throw new TrackerError('invalid_request', `${subject}: фильтр ${name} — список непустых строк.`);\n }\n continue;\n }\n if (value === null) continue; // null — значение фильтра: assignee null — задачи без исполнителя.\n if (typeof value === 'string') {\n if (value.trim() === '') throw new TrackerError('invalid_request', `${subject}: фильтр ${name} — пустая строка.`);\n continue;\n }\n if (Array.isArray(value)) {\n if (value.some((item) => typeof item !== 'string' || item.trim() === '')) {\n throw new TrackerError('invalid_request', `${subject}: фильтр ${name} — список непустых строк.`);\n }\n continue;\n }\n throw new TrackerError('invalid_request', `${subject}: фильтр ${name} — строка, список строк или null.`);\n }\n}\n\n/** Фильтры времени единой модели называются …After и …Before (createdAfter, updatedBefore). */\nfunction isTimeFilter(name: string): boolean {\n return name.endsWith('After') || name.endsWith('Before');\n}\n\n/** Списковые фильтры единой модели (status, labels): значение — массив строк, скалер здесь — опечатка вызова. */\nfunction isArrayFilter(name: string): boolean {\n return name === 'status' || name === 'labels';\n}\n\n/** Проверка запроса комментариев: updatedAfter вне filters или order вне capabilities.order — unsupported. */\nexport function assertCommentQuery(subject: string, capabilities: CommentCapabilities, query: CommentQuery): void {\n assertListQuery(subject, { filters: capabilities.filters, clientSide: capabilities.clientSide, sorts: [] }, query, COMMENT_FILTERS);\n if (query.order !== undefined && !capabilities.order.includes(query.order)) {\n throw new TrackerError('unsupported', `${subject}: порядок ${query.order} не поддерживается.`);\n }\n}\n\n/** Возможности задач трекера: раздел issues или LEGACY_ISSUE_CAPABILITIES. */\nexport function issueCapabilitiesOf(definition: TrackerDefinition): IssueCapabilities {\n return definition.issues ?? LEGACY_ISSUE_CAPABILITIES;\n}\n\n/** Мс единой модели → ISO 8601 UTC для параметров трекера. */\nexport function isoTime(ms: number): string {\n return new Date(ms).toISOString();\n}\n\n/** Время записи в границах [after, before] включительно; граница задана, а время неизвестно — не проходит. */\nexport function inTimeRange(value: number | undefined, after: number | undefined, before: number | undefined): boolean {\n if (after === undefined && before === undefined) return true;\n if (value === undefined) return false;\n return (after === undefined || value >= after) && (before === undefined || value <= before);\n}\n\n/** Есть ли needle (без учёта регистра) подстрокой в одном из текстов. */\nexport function containsText(texts: readonly (string | undefined)[], needle: string): boolean {\n const lower = needle.toLowerCase();\n return texts.some((value) => value !== undefined && value.toLowerCase().includes(lower));\n}\n\n/** Значение в двойных кавычках для JQL, QL SourceCraft и q поиска GitHub: экранирует \\ и \". */\nexport function quoted(value: string): string {\n return `\"${value.replace(/[\\\\\"]/g, '\\\\$&')}\"`;\n}\n\n/** Ключи таблицы сопоставления, чьё значение — одна из категорий (обратный поиск для фильтров трекера). */\nexport function keysFor<T>(table: Readonly<Record<string, T>>, values: readonly T[]): string[] {\n return Object.entries(table)\n .filter(([, value]) => values.includes(value))\n .map(([key]) => key);\n}\n","// Таблицы сопоставления статусов и приоритетов трекеров библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/mapping.const.ts — дословная копия, импорт типов из среза контракта библиотеки;\n// SOURCECRAFT_STATUS_FILTER — свой (#14).\nimport type { IssuePriority, IssueStatusCategory } from '../contract/contract.types.ts';\n\n// Сопоставление статусов и приоритетов трекеров с единой моделью (D-351). Ключ — слаг или имя у трекера,\n// значение — категория единой модели. Не найденное в таблице: статус → `open`, приоритет не заполняется.\n\n/** SourceCraft: системные статусы. На паузе — ещё не закончено, но и не в работе: `open`. */\nexport const SOURCECRAFT_STATUSES: Readonly<Record<string, IssueStatusCategory>> = {\n open: 'open',\n paused: 'open',\n inProgress: 'in_progress',\n closed: 'done',\n declined: 'declined',\n duplicate: 'declined',\n};\n\n/** Категория → слаг статуса SourceCraft при переводе задачи. */\nexport const SOURCECRAFT_STATUS_SLUGS: Readonly<Record<IssueStatusCategory, string>> = {\n open: 'open',\n in_progress: 'inProgress',\n done: 'closed',\n declined: 'declined',\n};\n\n/** Категория → слаги статусов QL фильтра списка (`status in (…)`); QL принимает только слаги, не имена. */\nexport const SOURCECRAFT_STATUS_FILTER: Readonly<Record<IssueStatusCategory, readonly string[]>> = {\n open: ['open', 'paused'],\n in_progress: ['in_progress'],\n done: ['closed'],\n declined: ['declined', 'duplicate'],\n};\n\n/** Приоритеты SourceCraft совпадают с единой моделью по именам. */\nexport const SOURCECRAFT_PRIORITIES: Readonly<Record<string, IssuePriority>> = {\n trivial: 'trivial',\n minor: 'minor',\n normal: 'normal',\n critical: 'critical',\n blocker: 'blocker',\n};\n\n/** Jira: `statusCategory.key` статуса. */\nexport const JIRA_STATUS_CATEGORIES: Readonly<Record<string, IssueStatusCategory>> = {\n new: 'open',\n indeterminate: 'in_progress',\n done: 'done',\n};\n\n/** Jira: имена приоритетов схемы по умолчанию (регистр не важен, ключи в нижнем). */\nexport const JIRA_PRIORITIES: Readonly<Record<string, IssuePriority>> = {\n lowest: 'trivial',\n low: 'minor',\n medium: 'normal',\n high: 'critical',\n highest: 'blocker',\n};\n\n/** Категория → имя приоритета Jira при создании и правке. */\nexport const JIRA_PRIORITY_NAMES: Readonly<Record<IssuePriority, string>> = {\n trivial: 'Lowest',\n minor: 'Low',\n normal: 'Medium',\n critical: 'High',\n blocker: 'Highest',\n};\n\n/** Тип задачи Jira, который создаёт адаптер. */\nexport const JIRA_ISSUE_TYPE = 'Task';\n\n/** GitHub: причина закрытия `state_reason`. */\nexport const GITHUB_CLOSE_REASONS: Readonly<Record<string, IssueStatusCategory>> = {\n completed: 'done',\n not_planned: 'declined',\n duplicate: 'declined',\n};\n\n/** GitLab: приоритеты нет, но принято помечать задачи метками `priority::<имя>`; метка читается как приоритет. */\nexport const GITLAB_PRIORITY_LABELS: Readonly<Record<string, IssuePriority>> = {\n 'priority::trivial': 'trivial',\n 'priority::minor': 'minor',\n 'priority::normal': 'normal',\n 'priority::critical': 'critical',\n 'priority::blocker': 'blocker',\n};\n\n/** Метка GitLab, которой адаптер отмечает «в работе»: у GitLab только opened и closed. */\nexport const GITLAB_IN_PROGRESS_LABEL = 'status::in-progress';\n\n/** Метка GitHub для «в работе» — по той же причине. */\nexport const GITHUB_IN_PROGRESS_LABEL = 'in progress';\n\n/** Метки GitHub для приоритета: `priority: <имя>`. */\nexport const GITHUB_PRIORITY_LABELS: Readonly<Record<string, IssuePriority>> = {\n 'priority: trivial': 'trivial',\n 'priority: minor': 'minor',\n 'priority: normal': 'normal',\n 'priority: critical': 'critical',\n 'priority: blocker': 'blocker',\n};\n\nexport const ALL_STATUSES: readonly IssueStatusCategory[] = ['open', 'in_progress', 'done', 'declined'];\n","// JSON-запросы к REST внешних трекеров библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/http.lib.ts — дословная копия, redactSecretText — из ядра библиотеки\n// (общий redactor ядра, kernel/redact.lib.ts); отказы not_found, conflict и rate_limited — свои (#14).\nimport { redactSecretText } from '../kernel/redact.lib.ts';\nimport { TRACKER_ERROR_BODY_MAX, TRACKER_TIMEOUT_MS } from './tracker.const.ts';\nimport { TrackerError } from './tracker.lib.ts';\nimport type { JsonRequest, JsonResponse } from './tracker.types.ts';\n\n// Запрос к REST внешнего трекера: JSON в обе стороны, таймаут, ошибки без токена (D-352, D-353).\n\nexport async function requestJson(url: string, request: JsonRequest): Promise<JsonResponse> {\n let response: Response;\n try {\n response = await request.fetch(url, {\n method: request.method ?? 'GET',\n headers: { accept: 'application/json', ...(request.body === undefined ? {} : { 'content-type': 'application/json' }), ...request.headers },\n ...(request.body === undefined ? {} : { body: JSON.stringify(request.body) }),\n signal: AbortSignal.timeout(TRACKER_TIMEOUT_MS),\n });\n } catch (error) {\n throw new TrackerError('failed', redactSecretText(`Трекер не ответил (${hostOf(url)}): ${error instanceof Error ? error.message : String(error)}`));\n }\n const raw = await response.text();\n if (!response.ok) throw failureOf(url, response, raw, request);\n if (raw === '') return { body: undefined, headers: response.headers };\n try {\n return { body: JSON.parse(raw) as unknown, headers: response.headers };\n } catch {\n throw new TrackerError('failed', `Трекер ${hostOf(url)} вернул не JSON.`);\n }\n}\n\n/**\n * Отказ по ответу не 2xx, по порядку: 404 с missing или missingIsIssue, статус из conflictOn — conflict,\n * 429, а также 403 с x-ratelimit-remaining: 0 или retry-after — rate_limited (retry-after без исчерпанного\n * лимита — вторичный лимит частоты GitHub), иначе failed. Тело ответа — без секретов и не длиннее потолка.\n */\nfunction failureOf(url: string, response: Response, raw: string, request: Pick<JsonRequest, 'missing' | 'missingIsIssue' | 'conflictOn'>): TrackerError {\n const status = response.status;\n if (status === 404 && request.missing !== undefined) return new TrackerError(request.missing.failure, request.missing.message);\n if (status === 404 && request.missingIsIssue === true) return new TrackerError('unknown_issue', 'Задача не найдена в трекере.');\n const detail = redactSecretText(raw.replace(/\\s+/g, ' ').trim()).slice(0, TRACKER_ERROR_BODY_MAX);\n const answered = `Трекер ${hostOf(url)} ответил ${String(status)}${detail === '' ? '' : `: ${detail}`}.`;\n if (request.conflictOn?.includes(status) === true) return new TrackerError('conflict', answered);\n const secondaryLimit = status === 403 && (response.headers.get('x-ratelimit-remaining')?.trim() === '0' || retryAfterOf(response.headers.get('retry-after')?.trim(), Date.now()) !== undefined);\n if (status === 429 || secondaryLimit) {\n const delay = retryDelayOf(response.headers);\n return new TrackerError('rate_limited', `Трекер ${hostOf(url)} ограничил частоту запросов${delay === undefined ? '' : `, повтор через ${String(delay)} с`}.`);\n }\n return new TrackerError('failed', answered);\n}\n\n/**\n * Через сколько секунд повторить: retry-after (секунды или HTTP-дата), иначе x-ratelimit-reset (GitHub, epoch секунд),\n * иначе ratelimit-reset (GitLab); не разобралось — undefined.\n */\nfunction retryDelayOf(headers: Headers, now: number = Date.now()): number | undefined {\n const retryAfter = retryAfterOf(headers.get('retry-after')?.trim(), now);\n if (retryAfter !== undefined) return retryAfter;\n for (const name of ['x-ratelimit-reset', 'ratelimit-reset']) {\n const reset = headers.get(name)?.trim();\n if (reset !== undefined && /^\\d+$/.test(reset)) return resetDelay(Number(reset), now);\n }\n return undefined;\n}\n\n/** retry-after — число секунд или HTTP-дата; пустой и неразборчивый — undefined. */\nfunction retryAfterOf(value: string | undefined, now: number): number | undefined {\n if (value === undefined || value === '') return undefined;\n if (/^\\d+$/.test(value)) return Number(value);\n const at = Date.parse(value);\n return Number.isFinite(at) ? Math.max(0, Math.ceil((at - now) / 1000)) : undefined;\n}\n\n/** Сброс лимита: epoch секунд (от 1e9, 2001-09-09) — задержка до него от now; меньшее число — уже задержка в секундах. */\nfunction resetDelay(reset: number, now: number): number {\n return reset >= 1_000_000_000 ? Math.max(0, reset - Math.floor(now / 1000)) : reset;\n}\n\n/** Адрес без пути и параметров: в тексте ошибки секретам неоткуда взяться. */\nfunction hostOf(url: string): string {\n try {\n return new URL(url).host;\n } catch {\n return 'трекер';\n }\n}\n\n/** Базовый адрес без хвостовых слэшей; не http и не https — отказ подключения. */\nexport function baseUrl(value: string | undefined, fallback: string): string {\n const raw = (value ?? fallback).replace(/\\/+$/, '');\n let parsed: URL;\n try {\n parsed = new URL(raw);\n } catch {\n throw new TrackerError('invalid_request', 'Адрес трекера — не URL.');\n }\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') throw new TrackerError('invalid_request', 'Адрес трекера должен быть http или https.');\n return raw;\n}\n","// Реестр трекеров библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/registry.lib.ts — дословная копия. Побочных эффектов при импорте нет:\n// реестр пуст, наполняется только явными вызовами registerTracker/registerBuiltinTrackers (R-001).\nimport type { TrackerDefinition } from './tracker.types.ts';\n\n// Реестр трекеров (D-350): вид подключения → определение. Потребитель работает только через него;\n// новый трекер — модуль с `TrackerDefinition` и одна строка регистрации в `builtin.lib.ts`.\n\nconst definitions = new Map<string, TrackerDefinition>();\n\n/** Регистрирует трекер; повтор того же вида — ошибка сборки, а не замена. */\nexport function registerTracker(definition: TrackerDefinition): void {\n const kind = definition.descriptor.tracker;\n if (definitions.has(kind)) throw new Error(`Трекер ${kind} уже зарегистрирован.`);\n definitions.set(kind, definition);\n}\n\nexport function findTracker(kind: string): TrackerDefinition | undefined {\n return definitions.get(kind);\n}\n\nexport function listTrackers(): TrackerDefinition[] {\n return [...definitions.values()];\n}\n","// Адаптер GitHub библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/github.lib.ts — дословная копия, импорт типов из среза контракта библиотеки;\n// возможности фильтров, маршрутизация /issues ↔ Search API и since комментариев — свои (#14).\nimport type { Issue, IssueComment, IssuePriority, IssueStatusCategory } from '../contract/contract.types.ts';\nimport { baseUrl, requestJson } from './http.lib.ts';\nimport { GITHUB_CLOSE_REASONS, GITHUB_IN_PROGRESS_LABEL, GITHUB_PRIORITY_LABELS } from './mapping.const.ts';\nimport { ISSUE_FILTERS } from './tracker.const.ts';\nimport { TrackerError, assertCommentQuery, assertListQuery, isRecord, isoTime, lookup, priorityName, quoted, requireTarget, stringList, text, toTimestamp } from './tracker.lib.ts';\nimport type { AdapterContext, IssueCapabilities, IssuePatchInput, IssueQuery, TrackerAdapter, TrackerDefinition, TrackerPage } from './tracker.types.ts';\n\n// Трекер GitHub (D-350): задачи репозитория `owner/repo` через REST API. У GitHub статус — open или closed\n// с причиной: «в работе» держится меткой `in progress`, приоритет — меткой `priority: <имя>`; обе метки\n// читаются в поля единой модели и из `labels` убираются. Pull request-ы в списке задач пропускаются.\n// Список идёт через `/issues`, а поиск по тексту и границы created/updated-before есть только в Search API (#14).\n\nconst DEFAULT_API = 'https://api.github.com';\nconst TARGET = /^[\\w.-]+\\/[\\w.-]+$/;\nconst NUMBER = /^[1-9]\\d{0,14}$/;\nconst LIST_SUBJECT = 'Задачи GitHub';\nconst COMMENTS_SUBJECT = 'Комментарии GitHub';\n\nexport function githubTracker(): TrackerDefinition {\n // Возможности по задачам (§3.6): статус GitHub не фильтрует, поэтому проверяется по полученной странице;\n // комментарии — только по времени изменения и только в порядке asc.\n const issues: IssueCapabilities = {\n list: { filters: ISSUE_FILTERS, clientSide: ['status'], sorts: ['created', 'updated', 'comments'] },\n comments: { filters: ['updatedAfter'], clientSide: [], order: ['asc'] },\n };\n return {\n descriptor: {\n tracker: 'github',\n title: 'GitHub',\n fields: [\n { name: 'target', required: true, secret: false },\n { name: 'token', required: true, secret: true },\n { name: 'url', required: false, secret: false },\n ],\n features: { create: true, update: true, comment: true, priority: true, labels: true, assignee: true, statuses: ['open', 'in_progress', 'done', 'declined'] },\n },\n create: (context) => createGithubAdapter(context, issues),\n issues,\n };\n}\n\nfunction createGithubAdapter({ connection, fetch }: AdapterContext, capabilities: IssueCapabilities): TrackerAdapter {\n const target = requireTarget(connection.target, 'owner/repo репозитория GitHub');\n if (!TARGET.test(target)) throw new TrackerError('invalid_request', 'target GitHub — owner/repo.');\n const api = baseUrl(connection.url, DEFAULT_API);\n const root = `${api}/repos/${target}/issues`;\n const headers = {\n accept: 'application/vnd.github+json',\n 'x-github-api-version': '2022-11-28',\n ...(connection.token === undefined || connection.token === '' ? {} : { authorization: `Bearer ${connection.token}` }),\n };\n const number = (key: string): string => {\n if (!NUMBER.test(key)) throw new TrackerError('unknown_issue', `В GitHub нет задачи ${key}.`);\n return key;\n };\n const rawOf = async (key: string): Promise<Record<string, unknown>> => {\n const { body } = await requestJson(`${root}/${number(key)}`, { fetch, headers, missingIsIssue: true });\n return isRecord(body) ? body : {};\n };\n return {\n list: async (query) => {\n assertListQuery(LIST_SUBJECT, capabilities.list, query, ISSUE_FILTERS);\n assertCsvLabels(query.labels);\n const page = pageOf(query.cursor);\n // Search API нужен, когда запрошено то, чего `/issues` не умеет: текст поиска и границы created/updated-before (§3.7 A2).\n const search = needsSearch(query);\n const params = search ? searchParams(target, query, page) : issuesParams(query, page);\n const { body, headers: responseHeaders } = await requestJson(`${search ? `${api}/search/issues` : root}?${params.toString()}`, { fetch, headers });\n return issuePageOf(rowsOf(body, search), query, responseHeaders.get('link') ?? '', page);\n },\n get: async (key) => issueOf(await rawOf(key)),\n create: async (input) => {\n const labels = composeLabels(input.labels ?? [], input.priority, undefined);\n const body = {\n title: input.title,\n ...(input.description === undefined ? {} : { body: input.description }),\n ...(labels.length === 0 ? {} : { labels }),\n ...(input.assignee === undefined ? {} : { assignees: [input.assignee] }),\n };\n return issueOf((await requestJson(root, { fetch, headers, method: 'POST', body })).body);\n },\n update: async (key, patch) => {\n const current = patch.labels === undefined && patch.priority === undefined && patch.status === undefined ? undefined : issueOf(await rawOf(key));\n const response = await requestJson(`${root}/${number(key)}`, { fetch, headers, method: 'PATCH', body: patchBody(patch, current), missingIsIssue: true });\n return issueOf(response.body);\n },\n comments: async (key, query) => {\n assertCommentQuery(COMMENTS_SUBJECT, capabilities.comments, query);\n const page = pageOf(query.cursor);\n const params = new URLSearchParams({ per_page: String(query.limit), page: String(page) });\n // `since` — изменения не раньше момента; порядок у GitHub один, по id (§3.7 A2).\n if (query.updatedAfter !== undefined) params.set('since', isoTime(query.updatedAfter));\n const { body, headers: responseHeaders } = await requestJson(`${root}/${number(key)}/comments?${params.toString()}`, { fetch, headers, missingIsIssue: true });\n return { items: (Array.isArray(body) ? body : []).map(commentOf), ...(/rel=\"next\"/.test(responseHeaders.get('link') ?? '') ? { nextCursor: String(page + 1) } : {}) };\n },\n comment: async (key, body) => commentOf((await requestJson(`${root}/${number(key)}/comments`, { fetch, headers, method: 'POST', body: { body }, missingIsIssue: true })).body),\n };\n}\n\nfunction pageOf(cursor: string | undefined): number {\n const page = cursor === undefined ? 1 : Number(cursor);\n return Number.isInteger(page) && page >= 1 ? page : 1;\n}\n\n/** Параметр `state` по запрошенным категориям; смешанный запрос — все, лишнее отсеет клиент. */\nfunction stateFilter(status: readonly IssueStatusCategory[] | undefined): string {\n if (status === undefined) return 'all';\n if (status.every((item) => item === 'open' || item === 'in_progress')) return 'open';\n if (status.every((item) => item === 'done' || item === 'declined')) return 'closed';\n return 'all';\n}\n\n/** Поиск по тексту и границы created/updated-before есть только в Search API — он и выбирает endpoint (§3.7 A2). */\nfunction needsSearch(query: IssueQuery): boolean {\n return query.search !== undefined || query.createdAfter !== undefined || query.createdBefore !== undefined || query.updatedBefore !== undefined;\n}\n\n/** CSV-параметр labels: запятая внутри метки читалась бы как разделитель списка — отказ до запроса (§3.2 R1). */\nfunction assertCsvLabels(labels: readonly string[] | undefined): void {\n if (labels?.some((label) => label.includes(',')) === true) throw new TrackerError('invalid_request', `${LIST_SUBJECT}: метка не должна содержать запятую.`);\n}\n\n/** Параметры `/issues`: сегодняшние плюс фильтры и сортировка, которые GitHub применяет сам. */\nfunction issuesParams(query: IssueQuery, page: number): URLSearchParams {\n const params = new URLSearchParams({ state: stateFilter(query.status), per_page: String(query.limit), page: String(page) });\n if (query.labels !== undefined && query.labels.length > 0) params.set('labels', query.labels.join(','));\n if (query.assignee !== undefined) params.set('assignee', query.assignee ?? 'none');\n if (query.author !== undefined) params.set('creator', query.author);\n if (query.updatedAfter !== undefined) params.set('since', isoTime(query.updatedAfter));\n if (query.sort !== undefined) {\n params.set('sort', query.sort.field);\n params.set('direction', query.sort.direction ?? 'desc');\n }\n return params;\n}\n\n/** Параметры поиска: `q` плюс страницы и сортировка с `order` вместо `direction`; без sort — created desc,\n * иначе GitHub сортирует по релевантности, а порядок по умолчанию у списка — новые первыми (§3.2 R4, §3.7 A2). */\nfunction searchParams(target: string, query: IssueQuery, page: number): URLSearchParams {\n const params = new URLSearchParams({ q: searchQuery(target, query), per_page: String(query.limit), page: String(page) });\n const sort = query.sort;\n params.set('sort', sort?.field ?? 'created');\n params.set('order', sort?.direction ?? 'desc');\n return params;\n}\n\n/** `q` поиска: репозиторий и тип, затем фильтры; свободный текст — одна фраза в кавычках (§3.2 R6). */\nfunction searchQuery(target: string, query: IssueQuery): string {\n const parts: string[] = [`repo:${target}`, 'is:issue'];\n const state = searchStateFilter(query.status);\n if (state !== undefined) parts.push(state);\n for (const label of query.labels ?? []) parts.push(`label:${quoted(label)}`);\n if (query.assignee !== undefined) parts.push(query.assignee === null ? 'no:assignee' : `assignee:${quoted(query.assignee)}`);\n if (query.author !== undefined) parts.push(`author:${quoted(query.author)}`);\n const created = timeRangeQualifier('created', query.createdAfter, query.createdBefore);\n if (created !== undefined) parts.push(created);\n const updated = timeRangeQualifier('updated', query.updatedAfter, query.updatedBefore);\n if (updated !== undefined) parts.push(updated);\n if (query.search !== undefined) parts.push(quoted(query.search));\n return parts.join(' ');\n}\n\n/** Границы поля времени в q: обе — один квалификатор-диапазон (два квалификатора GitHub объединяет через OR),\n * одна — >= / <=. ISO без кавычек: значение машинное ([0-9TZ:.-]), квалификатор из него не вставить (§3.2 R6). */\nfunction timeRangeQualifier(field: 'created' | 'updated', after: number | undefined, before: number | undefined): string | undefined {\n if (after !== undefined && before !== undefined) return `${field}:${isoTime(after)}..${isoTime(before)}`;\n if (after !== undefined) return `${field}:>=${isoTime(after)}`;\n if (before !== undefined) return `${field}:<=${isoTime(before)}`;\n return undefined;\n}\n\n/** Элементы ответа: `/issues` отдаёт массив, поиск — объект с `items` (§3.7 A2). */\nfunction rowsOf(body: unknown, search: boolean): readonly unknown[] {\n if (!search) return Array.isArray(body) ? body : [];\n return isRecord(body) && Array.isArray(body.items) ? body.items : [];\n}\n\n/** `is:open`/`is:closed` по запрошенным категориям; смешанный запрос — без него, лишнее отсеет страница. */\nfunction searchStateFilter(status: readonly IssueStatusCategory[] | undefined): string | undefined {\n if (status === undefined) return undefined;\n if (status.every((item) => item === 'open' || item === 'in_progress')) return 'is:open';\n if (status.every((item) => item === 'done' || item === 'declined')) return 'is:closed';\n return undefined;\n}\n\n/** Страница задач: pull request-ы пропускаются, статус сверяется с полученной страницей (§3.2 R5). */\nfunction issuePageOf(rows: readonly unknown[], query: IssueQuery, link: string, page: number): TrackerPage<Issue> {\n const items = rows.filter((row) => isRecord(row) && row.pull_request === undefined).map(issueOf);\n return {\n items: query.status === undefined ? items : items.filter((issue) => query.status?.includes(issue.status.category) === true),\n ...(/rel=\"next\"/.test(link) ? { nextCursor: String(page + 1) } : {}),\n };\n}\n\n/** Метки записи: пользовательские плюс служебные для приоритета и «в работе». */\nfunction composeLabels(plain: readonly string[], priority: IssuePriority | undefined, status: IssueStatusCategory | undefined): string[] {\n const priorityLabel = priority === undefined ? undefined : priorityName(GITHUB_PRIORITY_LABELS, priority);\n return [...plain, ...(priorityLabel === undefined ? [] : [priorityLabel]), ...(status === 'in_progress' ? [GITHUB_IN_PROGRESS_LABEL] : [])];\n}\n\nfunction patchBody(patch: IssuePatchInput, current: Issue | undefined): Record<string, unknown> {\n const status = patch.status ?? current?.status.category;\n const touchesLabels = patch.labels !== undefined || patch.priority !== undefined || patch.status !== undefined;\n return {\n ...(patch.title === undefined ? {} : { title: patch.title }),\n ...(patch.description === undefined ? {} : { body: patch.description }),\n ...(patch.status === undefined ? {} : { state: patch.status === 'done' || patch.status === 'declined' ? 'closed' : 'open', ...(patch.status === 'declined' ? { state_reason: 'not_planned' } : patch.status === 'done' ? { state_reason: 'completed' } : { state_reason: 'reopened' }) }),\n ...(touchesLabels ? { labels: composeLabels(patch.labels ?? current?.labels ?? [], patch.priority ?? current?.priority, status) } : {}),\n ...(patch.assignee === undefined ? {} : { assignees: patch.assignee === null ? [] : [patch.assignee] }),\n };\n}\n\nfunction issueOf(raw: unknown): Issue {\n const item = isRecord(raw) ? raw : {};\n const names = Array.isArray(item.labels) ? stringList(item.labels.map((label) => (isRecord(label) ? label.name : label))) : [];\n const closed = item.state === 'closed';\n const category: IssueStatusCategory = closed ? lookup(GITHUB_CLOSE_REASONS, item.state_reason, 'done') : names.includes(GITHUB_IN_PROGRESS_LABEL) ? 'in_progress' : 'open';\n const priority = names.map((name) => lookup<IssuePriority | undefined>(GITHUB_PRIORITY_LABELS, name, undefined)).find((value) => value !== undefined);\n const description = text(item.body);\n const assignee = isRecord(item.assignee) ? text(item.assignee.login) : undefined;\n const url = text(item.html_url);\n const createdAt = toTimestamp(item.created_at);\n const updatedAt = toTimestamp(item.updated_at);\n const number = typeof item.number === 'number' ? String(item.number) : '?';\n return {\n key: number,\n title: text(item.title) ?? number,\n ...(description === undefined ? {} : { description }),\n status: { category, name: closed ? `closed${typeof item.state_reason === 'string' ? ` (${item.state_reason})` : ''}` : category === 'in_progress' ? 'in progress' : 'open' },\n ...(priority === undefined ? {} : { priority }),\n labels: names.filter((name) => name !== GITHUB_IN_PROGRESS_LABEL && !Object.hasOwn(GITHUB_PRIORITY_LABELS, name)),\n ...(assignee === undefined ? {} : { assignee }),\n links: url === undefined ? [] : [{ url, title: 'GitHub' }],\n ...(createdAt === undefined ? {} : { createdAt }),\n ...(updatedAt === undefined ? {} : { updatedAt }),\n };\n}\n\nfunction commentOf(raw: unknown): IssueComment {\n const item = isRecord(raw) ? raw : {};\n const author = isRecord(item.user) ? text(item.user.login) : undefined;\n const createdAt = toTimestamp(item.created_at);\n return { id: typeof item.id === 'number' ? String(item.id) : '?', ...(author === undefined ? {} : { author }), body: typeof item.body === 'string' ? item.body : '', ...(createdAt === undefined ? {} : { createdAt }) };\n}\n","// Адаптер GitLab библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/gitlab.lib.ts — дословная копия, импорт типов из среза контракта библиотеки.\nimport type { Issue, IssueComment, IssuePriority, IssueStatusCategory } from '../contract/contract.types.ts';\nimport { baseUrl, requestJson } from './http.lib.ts';\nimport { GITLAB_IN_PROGRESS_LABEL, GITLAB_PRIORITY_LABELS } from './mapping.const.ts';\nimport { COMMENT_FILTERS, ISSUE_FILTERS } from './tracker.const.ts';\nimport type { IssueSortField } from './tracker.const.ts';\nimport { TrackerError, assertCommentQuery, assertListQuery, inTimeRange, isRecord, isoTime, lookup, priorityName, requireTarget, stringList, text, toTimestamp } from './tracker.lib.ts';\nimport type { AdapterContext, IssueCapabilities, IssuePatchInput, TrackerAdapter, TrackerDefinition } from './tracker.types.ts';\n\n// Трекер GitLab (D-350): задачи проекта (`group/project` или числовой id) через REST API v4, токен — PRIVATE-TOKEN.\n// У GitLab статус — opened или closed: «в работе» держится меткой `status::in-progress`, приоритет —\n// меткой `priority::<имя>`; служебные метки читаются в поля единой модели и из `labels` убираются. «Отклонена»\n// у GitLab нет. Исполнитель у GitLab задаётся по id пользователя, поэтому только показывается.\n\nconst DEFAULT_URL = 'https://gitlab.com';\nconst TARGET = /^(\\d{1,15}|[\\w.-]+(\\/[\\w.-]+)+)$/;\nconst IID = /^[1-9]\\d{0,14}$/;\n\n/** Возможности списков GitLab (#14): все фильтры единой модели, статус проверяется по странице; comments не сортируется. */\nconst ISSUE_CAPABILITIES: IssueCapabilities = {\n list: { filters: ISSUE_FILTERS, clientSide: ['status'], sorts: ['created', 'updated', 'priority', 'title'] },\n comments: { filters: COMMENT_FILTERS, clientSide: COMMENT_FILTERS, order: ['asc', 'desc'] },\n};\n\n/** Поле сортировки единой модели → order_by GitLab; comments GitLab не сортирует, до сюда не доходит. */\nconst ORDER_BY: Readonly<Partial<Record<IssueSortField, string>>> = {\n created: 'created_at',\n updated: 'updated_at',\n priority: 'priority',\n title: 'title',\n};\n\nexport function gitlabTracker(): TrackerDefinition {\n return {\n descriptor: {\n tracker: 'gitlab',\n title: 'GitLab',\n fields: [\n { name: 'target', required: true, secret: false },\n { name: 'token', required: true, secret: true },\n { name: 'url', required: false, secret: false },\n ],\n features: { create: true, update: true, comment: true, priority: true, labels: true, assignee: false, statuses: ['open', 'in_progress', 'done'] },\n },\n create: (context) => createGitlabAdapter(context),\n issues: ISSUE_CAPABILITIES,\n };\n}\n\nfunction createGitlabAdapter({ connection, fetch }: AdapterContext): TrackerAdapter {\n const target = requireTarget(connection.target, 'путь проекта GitLab, group/project, или его id');\n if (!TARGET.test(target)) throw new TrackerError('invalid_request', 'target GitLab — group/project или числовой id.');\n const root = `${baseUrl(connection.url, DEFAULT_URL)}/api/v4/projects/${encodeURIComponent(target)}/issues`;\n const headers: Record<string, string> = connection.token === undefined || connection.token === '' ? {} : { 'private-token': connection.token };\n const iid = (key: string): string => {\n if (!IID.test(key)) throw new TrackerError('unknown_issue', `В GitLab нет задачи ${key}.`);\n return key;\n };\n const currentOf = async (key: string): Promise<Issue> => issueOf((await requestJson(`${root}/${iid(key)}`, { fetch, headers, missingIsIssue: true })).body);\n return {\n list: async (query) => {\n assertListQuery('Задачи GitLab', ISSUE_CAPABILITIES.list, query, ISSUE_FILTERS);\n const page = pageOf(query.cursor);\n const params = new URLSearchParams({\n state: stateFilter(query.status),\n per_page: String(query.limit),\n page: String(page),\n order_by: query.sort === undefined ? 'created_at' : (ORDER_BY[query.sort.field] ?? 'created_at'),\n sort: query.sort?.direction ?? 'desc',\n });\n if (query.labels !== undefined && query.labels.length > 0) {\n if (query.labels.some((label) => label.includes(','))) throw new TrackerError('invalid_request', 'Задачи GitLab: метка не должна содержать запятую.');\n params.set('labels', query.labels.join(','));\n }\n if (query.assignee !== undefined) params.set(query.assignee === null ? 'assignee_id' : 'assignee_username', query.assignee === null ? 'None' : query.assignee);\n if (query.author !== undefined) params.set('author_username', query.author);\n if (query.search !== undefined) params.set('search', query.search);\n if (query.createdAfter !== undefined) params.set('created_after', isoTime(query.createdAfter));\n if (query.createdBefore !== undefined) params.set('created_before', isoTime(query.createdBefore));\n if (query.updatedAfter !== undefined) params.set('updated_after', isoTime(query.updatedAfter));\n if (query.updatedBefore !== undefined) params.set('updated_before', isoTime(query.updatedBefore));\n const { body, headers: responseHeaders } = await requestJson(`${root}?${params.toString()}`, { fetch, headers });\n const items = (Array.isArray(body) ? body : []).map(issueOf);\n const next = responseHeaders.get('x-next-page');\n return {\n items: query.status === undefined ? items : items.filter((issue) => query.status?.includes(issue.status.category) === true),\n ...(next === null || next === '' ? {} : { nextCursor: next }),\n };\n },\n get: currentOf,\n create: async (input) => {\n const labels = composeLabels(input.labels ?? [], input.priority, undefined);\n const body = { title: input.title, ...(input.description === undefined ? {} : { description: input.description }), ...(labels.length === 0 ? {} : { labels: labels.join(',') }) };\n return issueOf((await requestJson(root, { fetch, headers, method: 'POST', body })).body);\n },\n update: async (key, patch) => {\n const current = patch.labels === undefined && patch.priority === undefined && patch.status === undefined ? undefined : await currentOf(key);\n return issueOf((await requestJson(`${root}/${iid(key)}`, { fetch, headers, method: 'PUT', body: patchBody(patch, current), missingIsIssue: true })).body);\n },\n comments: async (key, query) => {\n assertCommentQuery('Комментарии GitLab', ISSUE_CAPABILITIES.comments, query);\n const page = pageOf(query.cursor);\n const params = new URLSearchParams({ sort: query.order ?? 'asc', order_by: 'created_at', per_page: String(query.limit), page: String(page) });\n const { body, headers: responseHeaders } = await requestJson(`${root}/${iid(key)}/notes?${params.toString()}`, { fetch, headers, missingIsIssue: true });\n const next = responseHeaders.get('x-next-page');\n // Системные заметки («изменил метку») — не комментарии; updatedAfter сверяется с сырым updated_at заметки.\n const items = (Array.isArray(body) ? body : [])\n .filter((note) => isRecord(note) && note.system !== true && inTimeRange(toTimestamp(note.updated_at), query.updatedAfter, undefined))\n .map(commentOf);\n return { items, ...(next === null || next === '' ? {} : { nextCursor: next }) };\n },\n comment: async (key, body) => commentOf((await requestJson(`${root}/${iid(key)}/notes`, { fetch, headers, method: 'POST', body: { body }, missingIsIssue: true })).body),\n };\n}\n\nfunction pageOf(cursor: string | undefined): number {\n const page = cursor === undefined ? 1 : Number(cursor);\n return Number.isInteger(page) && page >= 1 ? page : 1;\n}\n\nfunction stateFilter(status: readonly IssueStatusCategory[] | undefined): string {\n if (status === undefined) return 'all';\n if (status.every((item) => item === 'open' || item === 'in_progress')) return 'opened';\n if (status.every((item) => item === 'done' || item === 'declined')) return 'closed';\n return 'all';\n}\n\nfunction composeLabels(plain: readonly string[], priority: IssuePriority | undefined, status: IssueStatusCategory | undefined): string[] {\n const priorityLabel = priority === undefined ? undefined : priorityName(GITLAB_PRIORITY_LABELS, priority);\n return [...plain, ...(priorityLabel === undefined ? [] : [priorityLabel]), ...(status === 'in_progress' ? [GITLAB_IN_PROGRESS_LABEL] : [])];\n}\n\nfunction patchBody(patch: IssuePatchInput, current: Issue | undefined): Record<string, unknown> {\n const status = patch.status ?? current?.status.category;\n const touchesLabels = patch.labels !== undefined || patch.priority !== undefined || patch.status !== undefined;\n if (patch.status === 'declined') throw new TrackerError('invalid_request', 'В GitLab нет статуса «отклонена».');\n return {\n ...(patch.title === undefined ? {} : { title: patch.title }),\n ...(patch.description === undefined ? {} : { description: patch.description }),\n ...(patch.status === undefined ? {} : { state_event: patch.status === 'done' ? 'close' : 'reopen' }),\n ...(touchesLabels ? { labels: composeLabels(patch.labels ?? current?.labels ?? [], patch.priority ?? current?.priority, status).join(',') } : {}),\n };\n}\n\nfunction issueOf(raw: unknown): Issue {\n const item = isRecord(raw) ? raw : {};\n const names = stringList(item.labels);\n const closed = item.state === 'closed';\n const category: IssueStatusCategory = closed ? 'done' : names.includes(GITLAB_IN_PROGRESS_LABEL) ? 'in_progress' : 'open';\n const priority = names.map((name) => lookup<IssuePriority | undefined>(GITLAB_PRIORITY_LABELS, name, undefined)).find((value) => value !== undefined);\n const description = text(item.description);\n const assignees = Array.isArray(item.assignees) ? item.assignees : [];\n const first = assignees[0];\n const assignee = isRecord(first) ? text(first.username) : undefined;\n const url = text(item.web_url);\n const createdAt = toTimestamp(item.created_at);\n const updatedAt = toTimestamp(item.updated_at);\n const key = typeof item.iid === 'number' ? String(item.iid) : '?';\n return {\n key,\n title: text(item.title) ?? key,\n ...(description === undefined ? {} : { description }),\n status: { category, name: closed ? 'closed' : category === 'in_progress' ? 'in progress' : 'opened' },\n ...(priority === undefined ? {} : { priority }),\n labels: names.filter((name) => name !== GITLAB_IN_PROGRESS_LABEL && !Object.hasOwn(GITLAB_PRIORITY_LABELS, name)),\n ...(assignee === undefined ? {} : { assignee }),\n links: url === undefined ? [] : [{ url, title: 'GitLab' }],\n ...(createdAt === undefined ? {} : { createdAt }),\n ...(updatedAt === undefined ? {} : { updatedAt }),\n };\n}\n\nfunction commentOf(raw: unknown): IssueComment {\n const item = isRecord(raw) ? raw : {};\n const author = isRecord(item.author) ? text(item.author.username) : undefined;\n const createdAt = toTimestamp(item.created_at);\n return { id: typeof item.id === 'number' ? String(item.id) : '?', ...(author === undefined ? {} : { author }), body: typeof item.body === 'string' ? item.body : '', ...(createdAt === undefined ? {} : { createdAt }) };\n}\n","// Адаптер Jira библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/jira.lib.ts — дословная копия, импорт типов из среза контракта библиотеки;\n// фильтры и сортировка списков — свои (#14).\nimport type { Issue, IssueComment, IssuePriority, IssueStatusCategory } from '../contract/contract.types.ts';\nimport { baseUrl, requestJson } from './http.lib.ts';\nimport { JIRA_ISSUE_TYPE, JIRA_PRIORITIES, JIRA_PRIORITY_NAMES, JIRA_STATUS_CATEGORIES } from './mapping.const.ts';\nimport { COMMENT_FILTERS, ISSUE_FILTERS } from './tracker.const.ts';\nimport type { IssueSortField } from './tracker.const.ts';\nimport { TrackerError, assertCommentQuery, assertListQuery, inTimeRange, isRecord, lookup, quoted, requireTarget, stringList, text, toTimestamp } from './tracker.lib.ts';\nimport type { AdapterContext, IssueCapabilities, IssuePatchInput, IssueQuery, TrackerAdapter, TrackerDefinition } from './tracker.types.ts';\n\n// Трекер Jira (D-350): проект по ключу, REST API v2 (описание — обычный текст). Есть `user` — Basic (email и\n// API-токен Cloud), нет — Bearer (персональный токен Server и Data Center). Список — `/search/jql` Cloud, на\n// 404 — классический `/search` Server с курсором `s:<startAt>`. Статус — по `statusCategory`, меняется\n// переходом (transition) в нужную категорию; «отклонена» у Jira нет. Исполнитель у Cloud — accountId, поэтому\n// только показывается.\n\nconst PROJECT_KEY = /^[A-Z][A-Z0-9_]{0,49}$/;\nconst ISSUE_KEY = /^[A-Z][A-Z0-9_]{0,49}-[1-9]\\d{0,14}$/;\nconst FIELDS = 'summary,description,status,priority,labels,assignee,created,updated';\nconst CATEGORY_JQL: Readonly<Partial<Record<IssueStatusCategory, string>>> = { open: '\"To Do\"', in_progress: '\"In Progress\"', done: 'Done' };\n\n/** Возможности списков задач Jira (#14): все фильтры — в JQL на стороне Jira, порядок комментариев asc и desc. */\nconst ISSUE_CAPABILITIES: IssueCapabilities = {\n list: { filters: ISSUE_FILTERS, clientSide: [], sorts: ['created', 'updated', 'priority', 'title'] },\n comments: { filters: COMMENT_FILTERS, clientSide: COMMENT_FILTERS, order: ['asc', 'desc'] },\n};\n\n/** Поле сортировки единой модели → поле ORDER BY JQL; без сортировки — created DESC, как раньше. */\nconst JIRA_SORT_FIELDS: Readonly<Record<Exclude<IssueSortField, 'comments'>, string>> = { created: 'created', updated: 'updated', priority: 'priority', title: 'summary' };\n\nexport function jiraTracker(): TrackerDefinition {\n return {\n descriptor: {\n tracker: 'jira',\n title: 'Jira',\n fields: [\n { name: 'url', required: true, secret: false },\n { name: 'target', required: true, secret: false },\n { name: 'user', required: false, secret: false },\n { name: 'token', required: true, secret: true },\n ],\n features: { create: true, update: true, comment: true, priority: true, labels: true, assignee: false, statuses: ['open', 'in_progress', 'done'] },\n },\n create: (context) => createJiraAdapter(context),\n issues: ISSUE_CAPABILITIES,\n };\n}\n\nfunction createJiraAdapter({ connection, fetch }: AdapterContext): TrackerAdapter {\n if (connection.url === undefined) throw new TrackerError('invalid_request', 'Не задан адрес Jira.');\n const project = requireTarget(connection.target, 'ключ проекта Jira, например PROJ');\n if (!PROJECT_KEY.test(project)) throw new TrackerError('invalid_request', 'target Jira — ключ проекта: заглавные буквы и цифры.');\n const site = baseUrl(connection.url, connection.url);\n const api = `${site}/rest/api/2`;\n const token = connection.token ?? '';\n const headers = { authorization: connection.user === undefined ? `Bearer ${token}` : `Basic ${Buffer.from(`${connection.user}:${token}`).toString('base64')}` };\n const key = (value: string): string => {\n if (!ISSUE_KEY.test(value)) throw new TrackerError('unknown_issue', `В Jira нет задачи ${value}.`);\n return value;\n };\n const toIssue = (raw: unknown): Issue => issueOf(raw, site);\n const load = async (value: string): Promise<Issue> => toIssue((await requestJson(`${api}/issue/${key(value)}?fields=${FIELDS}`, { fetch, headers, missingIsIssue: true })).body);\n return {\n list: async (query) => {\n assertListQuery('Задачи Jira', ISSUE_CAPABILITIES.list, query, ISSUE_FILTERS);\n const jql = listJql(project, query);\n if (jql === undefined) return { items: [] };\n if (query.cursor?.startsWith('s:') !== true) {\n const params = new URLSearchParams({ jql, fields: FIELDS, maxResults: String(query.limit) });\n if (query.cursor !== undefined) params.set('nextPageToken', query.cursor);\n try {\n const { body } = await requestJson(`${api}/search/jql?${params.toString()}`, { fetch, headers });\n const record = isRecord(body) ? body : {};\n const next = text(record.nextPageToken);\n return { items: (Array.isArray(record.issues) ? record.issues : []).map(toIssue), ...(next === undefined || record.isLast === true ? {} : { nextCursor: next }) };\n } catch (error) {\n if (!(error instanceof TrackerError) || !error.message.includes(' 404')) throw error;\n }\n }\n const startAt = query.cursor?.startsWith('s:') === true ? Number(query.cursor.slice(2)) : 0;\n const params = new URLSearchParams({ jql, fields: FIELDS, maxResults: String(query.limit), startAt: String(Number.isInteger(startAt) && startAt >= 0 ? startAt : 0) });\n const { body } = await requestJson(`${api}/search?${params.toString()}`, { fetch, headers });\n const record = isRecord(body) ? body : {};\n const issues = Array.isArray(record.issues) ? record.issues : [];\n const total = typeof record.total === 'number' ? record.total : 0;\n const at = typeof record.startAt === 'number' ? record.startAt : 0;\n return { items: issues.map(toIssue), ...(at + issues.length < total && issues.length > 0 ? { nextCursor: `s:${String(at + issues.length)}` } : {}) };\n },\n get: load,\n create: async (input) => {\n const fields = {\n project: { key: project },\n summary: input.title,\n issuetype: { name: JIRA_ISSUE_TYPE },\n ...(input.description === undefined ? {} : { description: input.description }),\n ...(input.priority === undefined ? {} : { priority: { name: JIRA_PRIORITY_NAMES[input.priority] } }),\n ...(input.labels === undefined ? {} : { labels: input.labels.map((label) => label.replace(/\\s+/g, '-')) }),\n };\n const { body } = await requestJson(`${api}/issue`, { fetch, headers, method: 'POST', body: { fields } });\n const created = isRecord(body) ? text(body.key) : undefined;\n if (created === undefined) throw new TrackerError('failed', 'Jira создала задачу, но не вернула её ключ.');\n return load(created);\n },\n update: async (value, patch) => {\n const fields = fieldsOf(patch);\n if (Object.keys(fields).length > 0) await requestJson(`${api}/issue/${key(value)}`, { fetch, headers, method: 'PUT', body: { fields }, missingIsIssue: true });\n if (patch.status !== undefined) await transition(api, key(value), patch.status, fetch, headers);\n return load(value);\n },\n comments: async (value, query) => {\n assertCommentQuery('Комментарии Jira', ISSUE_CAPABILITIES.comments, query);\n const startAt = query.cursor === undefined ? 0 : Number(query.cursor);\n const params = new URLSearchParams({ startAt: String(Number.isInteger(startAt) && startAt >= 0 ? startAt : 0), maxResults: String(query.limit), orderBy: query.order === 'desc' ? '-created' : 'created' });\n const { body } = await requestJson(`${api}/issue/${key(value)}/comment?${params.toString()}`, { fetch, headers, missingIsIssue: true });\n const record = isRecord(body) ? body : {};\n const raw = Array.isArray(record.comments) ? record.comments : [];\n // Курсор считается по сырой странице: после дофильтровки updatedAfter остаток бывает пуст, а листание продолжается (§3.2 R5).\n const items = raw.filter((item) => inTimeRange(toTimestamp(isRecord(item) ? item.updated : undefined), query.updatedAfter, undefined));\n const total = typeof record.total === 'number' ? record.total : 0;\n const at = typeof record.startAt === 'number' ? record.startAt : 0;\n return { items: items.map(commentOf), ...(at + raw.length < total && raw.length > 0 ? { nextCursor: String(at + raw.length) } : {}) };\n },\n comment: async (value, body) => commentOf((await requestJson(`${api}/issue/${key(value)}/comment`, { fetch, headers, method: 'POST', body: { body }, missingIsIssue: true })).body),\n };\n}\n\n/** JQL списка (#14): project и дальше каждый фильтр через AND; undefined — статусов нет или Jira запрошенные\n * категории не знает (результат пуст, запроса нет, как раньше). */\nfunction listJql(project: string, query: IssueQuery): string | undefined {\n const clauses: string[] = [];\n if (query.status !== undefined) {\n const names = query.status.flatMap((item) => CATEGORY_JQL[item] ?? []);\n if (names.length === 0) return undefined;\n clauses.push(`statusCategory in (${names.join(', ')})`);\n }\n for (const label of query.labels ?? []) clauses.push(`labels = ${quoted(label.replace(/\\s+/g, '-'))}`);\n if (query.assignee !== undefined) clauses.push(query.assignee === null ? 'assignee is EMPTY' : `assignee = ${quoted(query.assignee)}`);\n if (query.author !== undefined) clauses.push(`reporter = ${quoted(query.author)}`);\n if (query.search !== undefined) clauses.push(`text ~ ${quoted(query.search)}`);\n if (query.createdAfter !== undefined) clauses.push(`created >= ${quoted(jiraTime(query.createdAfter, 'down'))}`);\n if (query.createdBefore !== undefined) clauses.push(`created <= ${quoted(jiraTime(query.createdBefore, 'up'))}`);\n if (query.updatedAfter !== undefined) clauses.push(`updated >= ${quoted(jiraTime(query.updatedAfter, 'down'))}`);\n if (query.updatedBefore !== undefined) clauses.push(`updated <= ${quoted(jiraTime(query.updatedBefore, 'up'))}`);\n const sort = query.sort;\n // 'comments' сюда не доходит: assertListQuery отказал раньше — в sorts Jira его нет.\n const field = (sort === undefined ? 'created' : sort.field) as Exclude<IssueSortField, 'comments'>;\n const direction = sort?.direction ?? 'desc';\n return `${[`project = ${quoted(project)}`, ...clauses].join(' AND ')} ORDER BY ${JIRA_SORT_FIELDS[field]} ${direction.toUpperCase()}`;\n}\n\n/** Время JQL: UTC, «yyyy/MM/dd HH:mm»; нижняя граница вниз к минуте, верхняя — вверх, чтобы границы были включительны (#14, R2). */\nfunction jiraTime(ms: number, outward: 'down' | 'up'): string {\n const at = new Date(outward === 'down' ? Math.floor(ms / 60000) * 60000 : Math.ceil(ms / 60000) * 60000);\n const pad = (value: number): string => String(value).padStart(2, '0');\n return `${String(at.getUTCFullYear())}/${pad(at.getUTCMonth() + 1)}/${pad(at.getUTCDate())} ${pad(at.getUTCHours())}:${pad(at.getUTCMinutes())}`;\n}\n\nfunction fieldsOf(patch: IssuePatchInput): Record<string, unknown> {\n return {\n ...(patch.title === undefined ? {} : { summary: patch.title }),\n ...(patch.description === undefined ? {} : { description: patch.description }),\n ...(patch.priority === undefined ? {} : { priority: { name: JIRA_PRIORITY_NAMES[patch.priority] } }),\n ...(patch.labels === undefined ? {} : { labels: patch.labels.map((label) => label.replace(/\\s+/g, '-')) }),\n };\n}\n\n/** Переводит задачу в категорию: берёт первый доступный переход, чей статус назначения лежит в ней. */\nasync function transition(api: string, key: string, category: IssueStatusCategory, fetch: AdapterContext['fetch'], headers: Record<string, string>): Promise<void> {\n const { body } = await requestJson(`${api}/issue/${key}/transitions`, { fetch, headers, missingIsIssue: true });\n const list = isRecord(body) && Array.isArray(body.transitions) ? body.transitions : [];\n const match = list.find((item) => {\n if (!isRecord(item) || !isRecord(item.to) || !isRecord(item.to.statusCategory)) return false;\n return lookup<IssueStatusCategory | undefined>(JIRA_STATUS_CATEGORIES, item.to.statusCategory.key, undefined) === category;\n });\n const id = isRecord(match) ? text(match.id) : undefined;\n if (id === undefined) throw new TrackerError('invalid_request', `Из текущего статуса Jira нет перехода в категорию ${category}.`);\n await requestJson(`${api}/issue/${key}/transitions`, { fetch, headers, method: 'POST', body: { transition: { id } }, missingIsIssue: true });\n}\n\nfunction issueOf(raw: unknown, site: string): Issue {\n const item = isRecord(raw) ? raw : {};\n const fields = isRecord(item.fields) ? item.fields : {};\n const status = isRecord(fields.status) ? fields.status : {};\n const category = isRecord(status.statusCategory) ? status.statusCategory.key : undefined;\n const priorityName = isRecord(fields.priority) && typeof fields.priority.name === 'string' ? fields.priority.name.toLowerCase() : undefined;\n const priority = lookup<IssuePriority | undefined>(JIRA_PRIORITIES, priorityName, undefined);\n const assignee = isRecord(fields.assignee) ? (text(fields.assignee.displayName) ?? text(fields.assignee.name)) : undefined;\n const description = text(fields.description);\n const createdAt = toTimestamp(fields.created);\n const updatedAt = toTimestamp(fields.updated);\n const key = text(item.key) ?? '?';\n return {\n key,\n title: text(fields.summary) ?? key,\n ...(description === undefined ? {} : { description }),\n status: { category: lookup(JIRA_STATUS_CATEGORIES, category, 'open'), name: text(status.name) ?? 'To Do' },\n ...(priority === undefined ? {} : { priority }),\n labels: stringList(fields.labels),\n ...(assignee === undefined ? {} : { assignee }),\n links: [{ url: `${site}/browse/${key}`, title: 'Jira' }],\n ...(createdAt === undefined ? {} : { createdAt }),\n ...(updatedAt === undefined ? {} : { updatedAt }),\n };\n}\n\nfunction commentOf(raw: unknown): IssueComment {\n const item = isRecord(raw) ? raw : {};\n const author = isRecord(item.author) ? text(item.author.displayName) : undefined;\n const createdAt = toTimestamp(item.created);\n return { id: text(item.id) ?? '?', ...(author === undefined ? {} : { author }), body: typeof item.body === 'string' ? item.body : '', ...(createdAt === undefined ? {} : { createdAt }) };\n}\n","// Локальный трекер библиотеки @smwb/onreel-git-mcp (часть E выделения, D-003).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/local.lib.ts — CRUD через функции ledger заменён на порт LocalIssueStore ядра\n// (kernel/store.types.ts): хранилище пишет потребитель (в onreel — поверх ledger), эталонная\n// реализация в памяти — в тестах библиотеки (test/helpers/tracker-fixtures.lib.ts).\n// Фильтры единой модели (#14): хранилище умеет только статус и keyset-страницы, остальные фильтры\n// адаптер проверяет по полученной странице — порт LocalIssueStore не меняется (D-003).\nimport type { Issue } from '../contract/contract.types.ts';\nimport type { LocalCommentRow, LocalIssueRow } from '../kernel/store.types.ts';\nimport { ALL_STATUSES } from './mapping.const.ts';\nimport { COMMENT_FILTERS, ISSUE_FILTERS } from './tracker.const.ts';\nimport { TrackerError, assertCommentQuery, assertListQuery, containsText, inTimeRange } from './tracker.lib.ts';\nimport type { AdapterContext, IssueCapabilities, IssueQuery, TrackerAdapter, TrackerDefinition } from './tracker.types.ts';\n\n// Локальный трекер (D-350): задачи в хранилище потребителя, без внешних сервисов. Номер задачи — её ключ.\n\nconst STATUS_NAMES = { open: 'Open', in_progress: 'In progress', done: 'Done', declined: 'Declined' } as const;\n\n/** Возможности списков локального трекера (#14, §3.6): из фильтров запроса хранилище знает только\n * статус, остальное проверяется по странице (D-004). Автора у локальной задачи нет и сортировки нет:\n * store отдаёт порядок ledger — новые первыми. */\nconst ISSUE_CAPABILITIES: IssueCapabilities = {\n list: {\n filters: ['status', 'labels', 'assignee', 'search', 'createdAfter', 'createdBefore', 'updatedAfter', 'updatedBefore'],\n clientSide: ['labels', 'assignee', 'search', 'createdAfter', 'createdBefore', 'updatedAfter', 'updatedBefore'],\n sorts: [],\n },\n comments: { filters: COMMENT_FILTERS, clientSide: COMMENT_FILTERS, order: ['asc'] },\n};\n\nexport function localTracker(): TrackerDefinition {\n return {\n descriptor: {\n tracker: 'local',\n title: 'Local',\n fields: [],\n features: { create: true, update: true, comment: true, priority: true, labels: true, assignee: true, statuses: [...ALL_STATUSES] },\n },\n issues: ISSUE_CAPABILITIES,\n create: (context) => createLocalAdapter(context),\n };\n}\n\nfunction createLocalAdapter({ store, projectId, author }: AdapterContext): TrackerAdapter {\n const number = (key: string): number => {\n if (!/^[1-9]\\d{0,14}$/.test(key)) throw new TrackerError('unknown_issue', `В локальном трекере нет задачи ${key}.`);\n return Number(key);\n };\n const mustGet = (key: string): LocalIssueRow => {\n const row = store.getLocalIssue(projectId, number(key));\n if (row === undefined) throw new TrackerError('unknown_issue', `В локальном трекере нет задачи ${key}.`);\n return row;\n };\n return {\n // list и comments async: отказ проверки запроса — rejected promise, как у остальных адаптеров.\n list: async (query) => {\n assertListQuery('Задачи Local', ISSUE_CAPABILITIES.list, query, ISSUE_FILTERS);\n const page = store.listLocalIssues(projectId, { limit: query.limit, ...(query.cursor === undefined ? {} : { cursor: query.cursor }), ...(query.status === undefined ? {} : { status: query.status }) });\n return { items: page.items.filter((row) => matchesIssueQuery(row, query)).map(toIssue), ...(page.nextCursor === undefined ? {} : { nextCursor: page.nextCursor }) };\n },\n get: (key) => Promise.resolve(toIssue(mustGet(key))),\n create: (input) => Promise.resolve(toIssue(store.createLocalIssue(projectId, input))),\n update: (key, patch) => {\n const row = store.updateLocalIssue(projectId, mustGet(key).number, patch);\n if (row === undefined) throw new TrackerError('unknown_issue', `В локальном трекере нет задачи ${key}.`);\n return Promise.resolve(toIssue(row));\n },\n comments: async (key, query) => {\n assertCommentQuery('Комментарии Local', ISSUE_CAPABILITIES.comments, query);\n const page = store.listLocalComments(projectId, mustGet(key).number, { limit: query.limit, ...(query.cursor === undefined ? {} : { cursor: query.cursor }) });\n // Локальные комментарии не правятся, поэтому updatedAfter сверяется с createdAt; порядок — только asc (§3.7 A6).\n const items = query.updatedAfter === undefined ? page.items : page.items.filter((row) => inTimeRange(row.createdAt, query.updatedAfter, undefined));\n return { items: items.map(toComment), ...(page.nextCursor === undefined ? {} : { nextCursor: page.nextCursor }) };\n },\n comment: (key, body) => Promise.resolve(toComment(store.addLocalComment(projectId, mustGet(key).number, body, author))),\n };\n}\n\n/** Фильтры единой модели, которые локальный трекер проверяет по странице (D-004): метки — все сразу (И),\n * assignee null — задачи без исполнителя, search — подстрока заголовка или описания без учёта регистра,\n * время — включительно с обеих сторон (R2, R3). */\nfunction matchesIssueQuery(row: LocalIssueRow, query: IssueQuery): boolean {\n if (query.labels !== undefined && !query.labels.every((label) => row.labels.includes(label))) return false;\n const assignee = query.assignee;\n if (assignee !== undefined && (assignee === null ? row.assignee !== undefined : row.assignee !== assignee)) return false;\n if (query.search !== undefined && !containsText([row.title, row.description], query.search)) return false;\n return inTimeRange(row.createdAt, query.createdAfter, query.createdBefore) && inTimeRange(row.updatedAt, query.updatedAfter, query.updatedBefore);\n}\n\nfunction toIssue(row: LocalIssueRow): Issue {\n return {\n key: String(row.number),\n title: row.title,\n ...(row.description === undefined ? {} : { description: row.description }),\n status: { category: row.status, name: STATUS_NAMES[row.status] },\n ...(row.priority === undefined ? {} : { priority: row.priority }),\n labels: row.labels,\n ...(row.assignee === undefined ? {} : { assignee: row.assignee }),\n links: [],\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n}\n\nfunction toComment(row: LocalCommentRow): { id: string; author?: string; body: string; createdAt: number } {\n return { id: String(row.id), ...(row.author === undefined ? {} : { author: row.author }), body: row.body, createdAt: row.createdAt };\n}\n","// Адаптер SourceCraft библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/sourcecraft.lib.ts — дословная копия, импорт типов из среза контракта библиотеки;\n// фильтры и сортировка списков — свои (#14): QL filter, sort_by, проверка по возможностям.\nimport type { Issue, IssueComment } from '../contract/contract.types.ts';\nimport { baseUrl, requestJson } from './http.lib.ts';\nimport { ALL_STATUSES, SOURCECRAFT_PRIORITIES, SOURCECRAFT_STATUSES, SOURCECRAFT_STATUS_FILTER, SOURCECRAFT_STATUS_SLUGS } from './mapping.const.ts';\nimport { COMMENT_FILTERS, ISSUE_FILTERS } from './tracker.const.ts';\nimport type { IssueSortField } from './tracker.const.ts';\nimport { TrackerError, assertCommentQuery, assertListQuery, inTimeRange, isRecord, isoTime, lookup, quoted, requireTarget, stringList, text, toTimestamp } from './tracker.lib.ts';\nimport type { AdapterContext, IssueCapabilities, IssuePatchInput, IssueQuery, TrackerAdapter, TrackerDefinition } from './tracker.types.ts';\n\n// Трекер SourceCraft (D-350): задачи репозитория `org/repo` через REST API, токен — Bearer. Исполнитель и метки\n// у SourceCraft задаются по id, а не по имени: адаптер их показывает, но не меняет.\n\nconst DEFAULT_API = 'https://api.sourcecraft.tech';\nconst DEFAULT_WEB = 'https://sourcecraft.dev';\nconst TARGET = /^[\\w.-]+\\/[\\w.-]+$/;\nconst SLUG = /^[\\w-]{1,100}$/;\n\n/** Поля сортировки единой модели → поля sort_by SourceCraft; comments адаптер не поддерживает (отказ в assertListQuery). */\nconst ISSUE_SORT_FIELDS_UPSTREAM: Readonly<Partial<Record<IssueSortField, string>>> = {\n created: 'created_at',\n updated: 'updated_at',\n priority: 'priority',\n title: 'title',\n};\n\n/** Возможности списков SourceCraft: QL фильтрует сервером; null исполнителя в списке и updatedAfter\n * комментариев проверяются по полученной странице (D-004). */\nconst ISSUE_CAPABILITIES: IssueCapabilities = {\n list: { filters: ISSUE_FILTERS, clientSide: ['assignee'], sorts: ['created', 'updated', 'priority', 'title'] },\n comments: { filters: COMMENT_FILTERS, clientSide: COMMENT_FILTERS, order: ['asc', 'desc'] },\n};\n\nexport function sourcecraftTracker(): TrackerDefinition {\n return {\n descriptor: {\n tracker: 'sourcecraft',\n title: 'SourceCraft',\n fields: [\n { name: 'target', required: true, secret: false },\n { name: 'token', required: true, secret: true },\n { name: 'url', required: false, secret: false },\n ],\n features: { create: true, update: true, comment: true, priority: true, labels: false, assignee: false, statuses: [...ALL_STATUSES] },\n },\n issues: ISSUE_CAPABILITIES,\n create: (context) => createSourceCraftAdapter(context),\n };\n}\n\nfunction createSourceCraftAdapter({ connection, fetch }: AdapterContext): TrackerAdapter {\n const target = requireTarget(connection.target, 'org/repo репозитория SourceCraft');\n if (!TARGET.test(target)) throw new TrackerError('invalid_request', 'target SourceCraft — org/repo.');\n const api = baseUrl(connection.url, DEFAULT_API);\n const root = `${api}/repos/${target}/issues`;\n const headers = { authorization: `Bearer ${connection.token ?? ''}` };\n const web = connection.url === undefined ? `${DEFAULT_WEB}/${target}/issues` : undefined;\n const slug = (key: string): string => {\n if (!SLUG.test(key)) throw new TrackerError('unknown_issue', `В SourceCraft нет задачи ${key}.`);\n return key;\n };\n const toIssue = (raw: unknown): Issue => issueOf(raw, web);\n return {\n list: async (query) => {\n assertListQuery('Задачи SourceCraft', ISSUE_CAPABILITIES.list, query, ISSUE_FILTERS);\n const params = new URLSearchParams({ page_size: String(query.limit) });\n if (query.cursor !== undefined) params.set('page_token', query.cursor);\n const filter = issueFilterOf(query);\n if (filter !== undefined) params.set('filter', filter);\n if (query.sort !== undefined) params.set('sort_by', `${query.sort.direction === 'asc' ? '' : '-'}${issueSortFieldOf(query.sort.field)}`);\n const { body } = await requestJson(`${root}?${params.toString()}`, { fetch, headers });\n const record = isRecord(body) ? body : {};\n let issues = (Array.isArray(record.issues) ? record.issues : []).map(toIssue);\n if (query.status !== undefined) issues = issues.filter((issue) => query.status?.includes(issue.status.category) === true);\n if (query.assignee === null) issues = issues.filter((issue) => issue.assignee === undefined);\n return { items: issues, ...nextOf(record.next_page_token) };\n },\n get: async (key) => toIssue((await requestJson(`${root}/${slug(key)}`, { fetch, headers, missingIsIssue: true })).body),\n create: async (input) => {\n const body = { title: input.title, ...(input.description === undefined ? {} : { description: input.description }), ...(input.priority === undefined ? {} : { priority: input.priority }) };\n return toIssue((await requestJson(root, { fetch, headers, method: 'POST', body })).body);\n },\n update: async (key, patch) => toIssue((await requestJson(`${root}/${slug(key)}`, { fetch, headers, method: 'PATCH', body: patchBody(patch), missingIsIssue: true })).body),\n comments: async (key, query) => {\n assertCommentQuery('Комментарии SourceCraft', ISSUE_CAPABILITIES.comments, query);\n const params = new URLSearchParams({ page_size: String(query.limit) });\n if (query.cursor !== undefined) params.set('page_token', query.cursor);\n if (query.order !== undefined) params.set('sort_by', query.order === 'asc' ? 'created_at' : '-created_at');\n const { body } = await requestJson(`${root}/${slug(key)}/comments?${params.toString()}`, { fetch, headers, missingIsIssue: true });\n const record = isRecord(body) ? body : {};\n const rawComments = Array.isArray(record.issue_comments) ? record.issue_comments : [];\n const filtered = query.updatedAfter === undefined ? rawComments : rawComments.filter((raw) => inTimeRange(toTimestamp(isRecord(raw) ? raw.updated_at : undefined), query.updatedAfter, undefined));\n return { items: filtered.map(commentOf), ...nextOf(record.next_page_token) };\n },\n comment: async (key, body) => commentOf((await requestJson(`${root}/${slug(key)}/comments`, { fetch, headers, method: 'POST', body: { body }, missingIsIssue: true })).body),\n };\n}\n\nfunction patchBody(patch: IssuePatchInput): Record<string, unknown> {\n return {\n ...(patch.title === undefined ? {} : { title: patch.title }),\n ...(patch.description === undefined ? {} : { description: patch.description }),\n ...(patch.status === undefined ? {} : { status_slug: SOURCECRAFT_STATUS_SLUGS[patch.status] }),\n ...(patch.priority === undefined ? {} : { priority: patch.priority }),\n };\n}\n\n/** Токен следующей страницы; пустая строка — последняя страница. */\nfunction nextOf(token: unknown): { nextCursor?: string } {\n const value = text(token);\n return value === undefined ? {} : { nextCursor: value };\n}\n\n/** Поле сортировки единой модели → поле sort_by SourceCraft; неподдерживаемое поле — отказ (R-002). */\nfunction issueSortFieldOf(field: IssueSortField): string {\n const upstream = ISSUE_SORT_FIELDS_UPSTREAM[field];\n if (upstream === undefined) throw new TrackerError('unsupported', `Задачи SourceCraft: сортировка по ${field} не поддерживается.`);\n return upstream;\n}\n\n/** QL фильтр списка задач: предложения через ` and `; исполнитель null — на странице, а не в QL (assignee_id=null даёт 500). */\nfunction issueFilterOf(query: IssueQuery): string | undefined {\n const clauses: string[] = [];\n if (query.status !== undefined && query.status.length > 0) {\n const slugs = [...new Set(query.status.flatMap((category) => SOURCECRAFT_STATUS_FILTER[category]))];\n clauses.push(`status in (${slugs.join(', ')})`);\n }\n for (const label of query.labels ?? []) clauses.push(`label_slug=${quoted(label)}`);\n if (typeof query.assignee === 'string') clauses.push(`assignee_slug=${quoted(query.assignee)}`);\n if (query.author !== undefined) clauses.push(`author_slug=${quoted(query.author)}`);\n if (query.search !== undefined) clauses.push(`title=${quoted(query.search)}`);\n if (query.createdAfter !== undefined) clauses.push(`created_at>=${quoted(isoTime(query.createdAfter))}`);\n if (query.createdBefore !== undefined) clauses.push(`created_at<=${quoted(isoTime(query.createdBefore))}`);\n if (query.updatedAfter !== undefined) clauses.push(`updated_at>=${quoted(isoTime(query.updatedAfter))}`);\n if (query.updatedBefore !== undefined) clauses.push(`updated_at<=${quoted(isoTime(query.updatedBefore))}`);\n return clauses.length === 0 ? undefined : clauses.join(' and ');\n}\n\nfunction issueOf(raw: unknown, web: string | undefined): Issue {\n const item = isRecord(raw) ? raw : {};\n const status = isRecord(item.status) ? item.status : {};\n const slug = text(item.slug) ?? '?';\n const statusSlug = text(status.slug) ?? 'open';\n const priority = lookup<Issue['priority']>(SOURCECRAFT_PRIORITIES, item.priority, undefined);\n const assignee = isRecord(item.assignee) ? text(item.assignee.slug) : undefined;\n const labels = Array.isArray(item.labels) ? stringList(item.labels.map((label) => (isRecord(label) ? label.name : undefined))) : [];\n const description = text(item.description);\n const createdAt = toTimestamp(item.created_at);\n const updatedAt = toTimestamp(item.updated_at);\n return {\n key: slug,\n title: text(item.title) ?? slug,\n ...(description === undefined ? {} : { description }),\n status: { category: lookup(SOURCECRAFT_STATUSES, statusSlug, 'open'), name: text(status.name) ?? statusSlug },\n ...(priority === undefined ? {} : { priority }),\n labels,\n ...(assignee === undefined ? {} : { assignee }),\n links: web === undefined ? [] : [{ url: `${web}/${slug}`, title: 'SourceCraft' }],\n ...(createdAt === undefined ? {} : { createdAt }),\n ...(updatedAt === undefined ? {} : { updatedAt }),\n };\n}\n\nfunction commentOf(raw: unknown): IssueComment {\n const item = isRecord(raw) ? raw : {};\n const author = isRecord(item.author) ? text(item.author.slug) : undefined;\n const createdAt = toTimestamp(item.created_at);\n return { id: text(item.id) ?? '?', ...(author === undefined ? {} : { author }), body: typeof item.body === 'string' ? item.body : '', ...(createdAt === undefined ? {} : { createdAt }) };\n}\n","// Встроенные трекеры библиотеки @smwb/onreel-git-mcp (часть E выделения, R-001).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/builtin.lib.ts — дословная копия. Регистрация была побочным эффектом импорта\n// guard.lib (onreel); в библиотеке она — только явный вызов registerBuiltinTrackers(), идемпотентный.\nimport { githubTracker } from './github.lib.ts';\nimport { gitlabTracker } from './gitlab.lib.ts';\nimport { jiraTracker } from './jira.lib.ts';\nimport { localTracker } from './local.lib.ts';\nimport { registerTracker } from './registry.lib.ts';\nimport { sourcecraftTracker } from './sourcecraft.lib.ts';\n\n// Трекеры, которые библиотека поставляет сама (D-350). Новый трекер добавляется модулем с\n// `TrackerDefinition` и строкой здесь: реестр и адаптеры не меняются.\n\nlet registered = false;\n\nexport function registerBuiltinTrackers(): void {\n if (registered) return;\n registered = true;\n for (const definition of [localTracker(), sourcecraftTracker(), githubTracker(), gitlabTracker(), jiraTracker()]) registerTracker(definition);\n}\n","// Хранение токенов подключений трекеров библиотеки @smwb/onreel-git-mcp (часть E выделения, D-352).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/secrets.lib.ts — копия; шов журнала host заменён на SecretSink ядра\n// (kernel/log.types.ts): по умолчанию defaultSecretSink общего redactor'а ядра (kernel/redact.lib.ts),\n// потребитель со своим журналом подставляет свой приёмник. Регистрация секрета не обязательна\n// для работы хранилища — это подсказка для маскирования текстов ошибок и журналов.\nimport { mkdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { defaultSecretSink } from '../kernel/redact.lib.ts';\nimport type { SecretSink } from '../kernel/log.types.ts';\nimport { TRACKER_SECRETS_FILE } from './tracker.const.ts';\nimport { isRecord } from './tracker.lib.ts';\n\n// Секреты подключений (D-352): токены по projectId в файле 0600 каталога данных потребителя. В хранилище\n// задач, ответы и журналы они не попадают: наружу идёт только признак «токен есть», а значение при чтении\n// и записи регистрируется в приёмнике секретов как известный секрет (D-194).\n\n/** Записи идут по одной: чтение-правка-запись двух подключений не затирает друг друга. */\nlet queue: Promise<unknown> = Promise.resolve();\n\nfunction exclusive<T>(task: () => Promise<T>): Promise<T> {\n const run = queue.then(task, task);\n queue = run.catch(() => undefined);\n return run;\n}\n\nasync function readAll(dataDir: string): Promise<Record<string, string>> {\n let raw: string;\n try {\n raw = await readFile(join(dataDir, TRACKER_SECRETS_FILE), 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return {};\n throw error;\n }\n const parsed: unknown = JSON.parse(raw);\n if (!isRecord(parsed)) return {};\n return Object.fromEntries(Object.entries(parsed).filter((entry): entry is [string, string] => typeof entry[1] === 'string'));\n}\n\nasync function writeAll(dataDir: string, secrets: Record<string, string>): Promise<void> {\n await mkdir(dataDir, { recursive: true, mode: 0o700 });\n const target = join(dataDir, TRACKER_SECRETS_FILE);\n const temp = `${target}.${String(process.pid)}.tmp`;\n await writeFile(temp, JSON.stringify(secrets), { mode: 0o600 });\n await rename(temp, target);\n}\n\n/** Токен проекта; undefined — не задан. Значение регистрируется в приёмнике секретов. */\nexport async function readTrackerToken(dataDir: string, projectId: string, sink: SecretSink = defaultSecretSink): Promise<string | undefined> {\n const token = (await readAll(dataDir))[projectId];\n if (token !== undefined) sink.register(token);\n return token;\n}\n\nexport function hasTrackerToken(dataDir: string, projectId: string): Promise<boolean> {\n return readAll(dataDir).then((secrets) => secrets[projectId] !== undefined);\n}\n\n/** Задаёт токен проекта; пустая строка убирает. */\nexport function writeTrackerToken(dataDir: string, projectId: string, token: string, sink: SecretSink = defaultSecretSink): Promise<void> {\n if (token !== '') sink.register(token);\n return exclusive(async () => {\n const secrets = await readAll(dataDir);\n if (token === '') delete secrets[projectId];\n else secrets[projectId] = token;\n await writeAll(dataDir, secrets);\n });\n}\n\nexport function deleteTrackerToken(dataDir: string, projectId: string, sink: SecretSink = defaultSecretSink): Promise<void> {\n return writeTrackerToken(dataDir, projectId, '', sink);\n}\n"],"mappings":"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","names":["TARGET","issueOf","pageOf","stateFilter","composeLabels","patchBody","commentOf","ISSUE_CAPABILITIES","toIssue","issueOf","params","body","record","commentOf","priorityName","ISSUE_CAPABILITIES","DEFAULT_API","TARGET","ISSUE_CAPABILITIES","toIssue","issueOf","patchBody","commentOf"]}
1
+ {"version":3,"sources":["../../src/tracker/tracker.const.ts","../../src/tracker/tracker.lib.ts","../../src/tracker/mapping.const.ts","../../src/tracker/http.lib.ts","../../src/tracker/registry.lib.ts","../../src/tracker/pull.schema.ts","../../src/tracker/github-pull.lib.ts","../../src/tracker/github.lib.ts","../../src/tracker/gitlab-pull.lib.ts","../../src/tracker/gitlab.lib.ts","../../src/tracker/jira.lib.ts","../../src/tracker/local.lib.ts","../../src/tracker/sourcecraft-pull.lib.ts","../../src/tracker/sourcecraft.lib.ts","../../src/tracker/builtin.lib.ts","../../src/tracker/secrets.lib.ts","../../src/tracker/pull.lib.ts"],"sourcesContent":["// Константы адаптеров трекеров библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/tracker.const.ts — дословная копия; фильтры и возможности списков — свои (#14).\nimport type { IssueCapabilities } from './tracker.types.ts';\n\n/** Потолок ожидания ответа внешнего трекера, мс. */\nexport const TRACKER_TIMEOUT_MS = 15_000;\n\n/** Размер страницы списка задач по умолчанию; потолок — 500 по контракту. */\nexport const TRACKER_PAGE_LIMIT_DEFAULT = 50;\n\n/** Сколько символов тела ответа трекера попадает в текст ошибки. */\nexport const TRACKER_ERROR_BODY_MAX = 300;\n\n/** Файл секретов подключений в каталоге данных host: токены трекеров по projectId, права 0600 (D-352). */\nexport const TRACKER_SECRETS_FILE = 'tracker-secrets.json';\n\n/** Автор комментариев, которые пользователь пишет в локальном трекере. */\nexport const TRACKER_LOCAL_AUTHOR = 'owner';\n\n/** Фильтры списка задач — имена полей IssueQuery; порядок — для текстов отказов. */\nexport const ISSUE_FILTERS = ['status', 'labels', 'assignee', 'author', 'search', 'createdAfter', 'createdBefore', 'updatedAfter', 'updatedBefore'] as const;\nexport type IssueFilter = (typeof ISSUE_FILTERS)[number];\n\n/** Поля сортировки задач единой модели. */\nexport const ISSUE_SORT_FIELDS = ['created', 'updated', 'priority', 'title', 'comments'] as const;\nexport type IssueSortField = (typeof ISSUE_SORT_FIELDS)[number];\n\n/** Фильтры списка комментариев — имена полей CommentQuery. */\nexport const COMMENT_FILTERS = ['updatedAfter'] as const;\nexport type CommentFilter = (typeof COMMENT_FILTERS)[number];\n\n/** Возможности трекера без раздела issues (свои трекеры потребителя): статус и страницы, комментарии по порядку. */\nexport const LEGACY_ISSUE_CAPABILITIES: IssueCapabilities = {\n list: { filters: ['status'], clientSide: ['status'], sorts: [] },\n comments: { filters: [], clientSide: [], order: ['asc'] },\n};\n","// Чистые помощники адаптеров трекеров библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/tracker.lib.ts — дословная копия, импорт типов из среза контракта библиотеки;\n// проверка запросов списков и помощники фильтров — свои (#14).\nimport type { IssuePriority, IssueStatusCategory } from '../contract/contract.types.ts';\nimport { COMMENT_FILTERS, LEGACY_ISSUE_CAPABILITIES } from './tracker.const.ts';\nimport type { CommentCapabilities, CommentQuery, IssueCapabilities, ListCapabilities, ListSort, TrackerDefinition, TrackerFailure } from './tracker.types.ts';\n\n/** Отказ адаптера: потребитель превращает его в ошибку своего контракта (D-353). */\nexport class TrackerError extends Error {\n readonly failure: TrackerFailure;\n constructor(failure: TrackerFailure, message: string) {\n super(message);\n this.name = 'TrackerError';\n this.failure = failure;\n }\n}\n\n/** Время трекера (ISO 8601) в миллисекунды; нет или не разобралось — undefined. */\nexport function toTimestamp(value: unknown): number | undefined {\n if (typeof value !== 'string') return undefined;\n const ms = Date.parse(value);\n return Number.isFinite(ms) && ms >= 0 ? ms : undefined;\n}\n\n/** Поле, которое задано: непустая строка. */\nexport function text(value: unknown): string | undefined {\n return typeof value === 'string' && value !== '' ? value : undefined;\n}\n\nexport function clipText(value: string, max: number): string {\n return value.length <= max ? value : value.slice(0, max);\n}\n\n/** Строки из массива неизвестного вида: непустые строки без дублей. */\nexport function stringList(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n return [...new Set(value.filter((item): item is string => typeof item === 'string' && item !== ''))];\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Категория и приоритет по таблице; нет в таблице — запасное значение. */\nexport function lookup<T>(table: Readonly<Record<string, T>>, key: unknown, fallback: T): T {\n return typeof key === 'string' && Object.hasOwn(table, key) ? (table[key] as T) : fallback;\n}\n\nexport function requireTarget(target: string | undefined, hint: string): string {\n if (target === undefined) throw new TrackerError('invalid_request', `Не задан target подключения: ${hint}.`);\n return target;\n}\n\n/** Обратная таблица: категория → первое имя статуса трекера. */\nexport function nameOf(table: Readonly<Record<string, IssueStatusCategory>>, category: IssueStatusCategory): string | undefined {\n return Object.entries(table).find(([, value]) => value === category)?.[0];\n}\n\nexport function priorityName(table: Readonly<Record<string, IssuePriority>>, priority: IssuePriority): string | undefined {\n return Object.entries(table).find(([, value]) => value === priority)?.[0];\n}\n\n/** Фильтры запроса со значением (не undefined и не пустой массив), в порядке names. */\nexport function usedFilters<F extends string>(query: Readonly<Partial<Record<F, unknown>>>, names: readonly F[]): F[] {\n return names.filter((name) => {\n const value = query[name];\n return value !== undefined && !(Array.isArray(value) && value.length === 0);\n });\n}\n\n/**\n * Проверка запроса списка по возможностям (D-004, R-002): фильтр со значением вне filters или sort.field вне sorts —\n * TrackerError('unsupported', `${subject}: фильтр ${name} не поддерживается.`); значение не той формы — invalid_request:\n * время не числом или не целое ≥ 0, пустая строка фильтра, список со строкой-пустышкой. subject — что за список:\n * 'Задачи GitHub', 'PR GitLab', 'Прогоны CI SourceCraft'.\n */\nexport function assertListQuery<F extends string, S extends string>(\n subject: string,\n capabilities: ListCapabilities<F, S>,\n query: Readonly<Partial<Record<F, unknown>>> & { readonly sort?: ListSort<S> | undefined },\n names: readonly F[],\n): void {\n const used = usedFilters(query, names);\n for (const name of used) {\n if (!capabilities.filters.includes(name)) throw new TrackerError('unsupported', `${subject}: фильтр ${name} не поддерживается.`);\n }\n const sort = query.sort;\n if (sort !== undefined && !capabilities.sorts.includes(sort.field)) {\n throw new TrackerError('unsupported', `${subject}: сортировка по ${sort.field} не поддерживается.`);\n }\n if (sort?.direction !== undefined && sort.direction !== 'asc' && sort.direction !== 'desc') {\n throw new TrackerError('invalid_request', `${subject}: направление сортировки — asc или desc.`);\n }\n // limit — поле PageQuery, а не фильтр: проверяется, когда запрос его несёт.\n const limit = (query as { readonly limit?: unknown }).limit;\n if (limit !== undefined && !(typeof limit === 'number' && Number.isSafeInteger(limit) && limit >= 1)) {\n throw new TrackerError('invalid_request', `${subject}: limit — целое число от 1.`);\n }\n for (const name of used) {\n const value = query[name];\n if (isTimeFilter(name)) {\n if (typeof value !== 'number' || !(Number.isSafeInteger(value) && value >= 0)) {\n throw new TrackerError('invalid_request', `${subject}: фильтр ${name} — время в мс, целое число от 0.`);\n }\n continue;\n }\n if (isArrayFilter(name)) {\n if (!Array.isArray(value) || value.some((item) => typeof item !== 'string' || item.trim() === '')) {\n throw new TrackerError('invalid_request', `${subject}: фильтр ${name} — список непустых строк.`);\n }\n continue;\n }\n if (value === null) continue; // null — значение фильтра: assignee null — задачи без исполнителя.\n if (typeof value === 'string') {\n if (value.trim() === '') throw new TrackerError('invalid_request', `${subject}: фильтр ${name} — пустая строка.`);\n continue;\n }\n if (Array.isArray(value)) {\n if (value.some((item) => typeof item !== 'string' || item.trim() === '')) {\n throw new TrackerError('invalid_request', `${subject}: фильтр ${name} — список непустых строк.`);\n }\n continue;\n }\n throw new TrackerError('invalid_request', `${subject}: фильтр ${name} — строка, список строк или null.`);\n }\n}\n\n/** Фильтры времени единой модели называются …After и …Before (createdAfter, updatedBefore). */\nfunction isTimeFilter(name: string): boolean {\n return name.endsWith('After') || name.endsWith('Before');\n}\n\n/** Списковые фильтры единой модели (status, labels): значение — массив строк, скалер здесь — опечатка вызова. */\nfunction isArrayFilter(name: string): boolean {\n return name === 'status' || name === 'labels';\n}\n\n/** Проверка запроса комментариев: updatedAfter вне filters или order вне capabilities.order — unsupported. */\nexport function assertCommentQuery(subject: string, capabilities: CommentCapabilities, query: CommentQuery): void {\n assertListQuery(subject, { filters: capabilities.filters, clientSide: capabilities.clientSide, sorts: [] }, query, COMMENT_FILTERS);\n if (query.order !== undefined && !capabilities.order.includes(query.order)) {\n throw new TrackerError('unsupported', `${subject}: порядок ${query.order} не поддерживается.`);\n }\n}\n\n/** Возможности задач трекера: раздел issues или LEGACY_ISSUE_CAPABILITIES. */\nexport function issueCapabilitiesOf(definition: TrackerDefinition): IssueCapabilities {\n return definition.issues ?? LEGACY_ISSUE_CAPABILITIES;\n}\n\n/** Мс единой модели → ISO 8601 UTC для параметров трекера. */\nexport function isoTime(ms: number): string {\n return new Date(ms).toISOString();\n}\n\n/** Время записи в границах [after, before] включительно; граница задана, а время неизвестно — не проходит. */\nexport function inTimeRange(value: number | undefined, after: number | undefined, before: number | undefined): boolean {\n if (after === undefined && before === undefined) return true;\n if (value === undefined) return false;\n return (after === undefined || value >= after) && (before === undefined || value <= before);\n}\n\n/** Есть ли needle (без учёта регистра) подстрокой в одном из текстов. */\nexport function containsText(texts: readonly (string | undefined)[], needle: string): boolean {\n const lower = needle.toLowerCase();\n return texts.some((value) => value !== undefined && value.toLowerCase().includes(lower));\n}\n\n/** Значение в двойных кавычках для JQL, QL SourceCraft и q поиска GitHub: экранирует \\ и \". */\nexport function quoted(value: string): string {\n return `\"${value.replace(/[\\\\\"]/g, '\\\\$&')}\"`;\n}\n\n/** Ключи таблицы сопоставления, чьё значение — одна из категорий (обратный поиск для фильтров трекера). */\nexport function keysFor<T>(table: Readonly<Record<string, T>>, values: readonly T[]): string[] {\n return Object.entries(table)\n .filter(([, value]) => values.includes(value))\n .map(([key]) => key);\n}\n","// Таблицы сопоставления статусов и приоритетов трекеров библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/mapping.const.ts — дословная копия, импорт типов из среза контракта библиотеки;\n// SOURCECRAFT_STATUS_FILTER — свой (#14); таблицы pull request-ов — свои (#15).\nimport type { IssuePriority, IssueStatusCategory } from '../contract/contract.types.ts';\nimport type { PullRequestStatusCategory } from './pull.schema.ts';\n\n// Сопоставление статусов и приоритетов трекеров с единой моделью (D-351). Ключ — слаг или имя у трекера,\n// значение — категория единой модели. Не найденное в таблице: статус → `open`, приоритет не заполняется.\n\n/** SourceCraft: системные статусы. На паузе — ещё не закончено, но и не в работе: `open`. */\nexport const SOURCECRAFT_STATUSES: Readonly<Record<string, IssueStatusCategory>> = {\n open: 'open',\n paused: 'open',\n inProgress: 'in_progress',\n closed: 'done',\n declined: 'declined',\n duplicate: 'declined',\n};\n\n/** Категория → слаг статуса SourceCraft при переводе задачи. */\nexport const SOURCECRAFT_STATUS_SLUGS: Readonly<Record<IssueStatusCategory, string>> = {\n open: 'open',\n in_progress: 'inProgress',\n done: 'closed',\n declined: 'declined',\n};\n\n/** Категория → слаги статусов QL фильтра списка (`status in (…)`); QL принимает только слаги, не имена. */\nexport const SOURCECRAFT_STATUS_FILTER: Readonly<Record<IssueStatusCategory, readonly string[]>> = {\n open: ['open', 'paused'],\n in_progress: ['in_progress'],\n done: ['closed'],\n declined: ['declined', 'duplicate'],\n};\n\n/** Приоритеты SourceCraft совпадают с единой моделью по именам. */\nexport const SOURCECRAFT_PRIORITIES: Readonly<Record<string, IssuePriority>> = {\n trivial: 'trivial',\n minor: 'minor',\n normal: 'normal',\n critical: 'critical',\n blocker: 'blocker',\n};\n\n/** Jira: `statusCategory.key` статуса. */\nexport const JIRA_STATUS_CATEGORIES: Readonly<Record<string, IssueStatusCategory>> = {\n new: 'open',\n indeterminate: 'in_progress',\n done: 'done',\n};\n\n/** Jira: имена приоритетов схемы по умолчанию (регистр не важен, ключи в нижнем). */\nexport const JIRA_PRIORITIES: Readonly<Record<string, IssuePriority>> = {\n lowest: 'trivial',\n low: 'minor',\n medium: 'normal',\n high: 'critical',\n highest: 'blocker',\n};\n\n/** Категория → имя приоритета Jira при создании и правке. */\nexport const JIRA_PRIORITY_NAMES: Readonly<Record<IssuePriority, string>> = {\n trivial: 'Lowest',\n minor: 'Low',\n normal: 'Medium',\n critical: 'High',\n blocker: 'Highest',\n};\n\n/** Тип задачи Jira, который создаёт адаптер. */\nexport const JIRA_ISSUE_TYPE = 'Task';\n\n/** GitHub: причина закрытия `state_reason`. */\nexport const GITHUB_CLOSE_REASONS: Readonly<Record<string, IssueStatusCategory>> = {\n completed: 'done',\n not_planned: 'declined',\n duplicate: 'declined',\n};\n\n/** GitLab: приоритеты нет, но принято помечать задачи метками `priority::<имя>`; метка читается как приоритет. */\nexport const GITLAB_PRIORITY_LABELS: Readonly<Record<string, IssuePriority>> = {\n 'priority::trivial': 'trivial',\n 'priority::minor': 'minor',\n 'priority::normal': 'normal',\n 'priority::critical': 'critical',\n 'priority::blocker': 'blocker',\n};\n\n/** Метка GitLab, которой адаптер отмечает «в работе»: у GitLab только opened и closed. */\nexport const GITLAB_IN_PROGRESS_LABEL = 'status::in-progress';\n\n/** Метка GitHub для «в работе» — по той же причине. */\nexport const GITHUB_IN_PROGRESS_LABEL = 'in progress';\n\n/** Метки GitHub для приоритета: `priority: <имя>`. */\nexport const GITHUB_PRIORITY_LABELS: Readonly<Record<string, IssuePriority>> = {\n 'priority: trivial': 'trivial',\n 'priority: minor': 'minor',\n 'priority: normal': 'normal',\n 'priority: critical': 'critical',\n 'priority: blocker': 'blocker',\n};\n\nexport const ALL_STATUSES: readonly IssueStatusCategory[] = ['open', 'in_progress', 'done', 'declined'];\n\n// Pull request-ы (D-005): состояние у трекера → категория единой модели.\n\n/** GitLab: state MR → категория; черновик — поле draft открытого MR. locked — слияние идёт, MR ещё открыт. */\nexport const GITLAB_MERGE_REQUEST_STATES: Readonly<Record<string, PullRequestStatusCategory>> = {\n opened: 'open',\n locked: 'open',\n merged: 'merged',\n closed: 'closed',\n};\n\n/** GitLab: префикс заголовка, которым адаптер делает MR черновиком. */\nexport const GITLAB_DRAFT_PREFIX = 'Draft: ';\n\n/** GitLab: все формы префикса черновика, которые снимаются при переводе в open. */\nexport const GITLAB_DRAFT_PATTERN = /^\\s*(?:\\[draft\\]|\\(draft\\)|draft:)\\s*/i;\n\n/** SourceCraft: состояния PR. merging — слияние идёт, PR ещё открыт; discarded — закрыт без слияния. */\nexport const SOURCECRAFT_PULL_STATUSES: Readonly<Record<string, PullRequestStatusCategory>> = {\n draft: 'draft',\n open: 'open',\n merging: 'open',\n merged: 'merged',\n discarded: 'closed',\n};\n","// JSON-запросы к REST внешних трекеров библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/http.lib.ts — дословная копия, redactSecretText — из ядра библиотеки\n// (общий redactor ядра, kernel/redact.lib.ts); отказы not_found, conflict и rate_limited — свои (#14).\nimport { redactSecretText } from '../kernel/redact.lib.ts';\nimport { TRACKER_ERROR_BODY_MAX, TRACKER_TIMEOUT_MS } from './tracker.const.ts';\nimport { TrackerError } from './tracker.lib.ts';\nimport type { JsonRequest, JsonResponse } from './tracker.types.ts';\n\n// Запрос к REST внешнего трекера: JSON в обе стороны, таймаут, ошибки без токена (D-352, D-353).\n\nexport async function requestJson(url: string, request: JsonRequest): Promise<JsonResponse> {\n let response: Response;\n try {\n response = await request.fetch(url, {\n method: request.method ?? 'GET',\n headers: { accept: 'application/json', ...(request.body === undefined ? {} : { 'content-type': 'application/json' }), ...request.headers },\n ...(request.body === undefined ? {} : { body: JSON.stringify(request.body) }),\n signal: AbortSignal.timeout(TRACKER_TIMEOUT_MS),\n });\n } catch (error) {\n throw new TrackerError('failed', redactSecretText(`Трекер не ответил (${hostOf(url)}): ${error instanceof Error ? error.message : String(error)}`));\n }\n const raw = await response.text();\n if (!response.ok) throw failureOf(url, response, raw, request);\n if (raw === '') return { body: undefined, headers: response.headers };\n try {\n return { body: JSON.parse(raw) as unknown, headers: response.headers };\n } catch {\n throw new TrackerError('failed', `Трекер ${hostOf(url)} вернул не JSON.`);\n }\n}\n\n/**\n * Отказ по ответу не 2xx, по порядку: 404 с missing или missingIsIssue, статус из conflictOn — conflict,\n * 429, а также 403 с x-ratelimit-remaining: 0 или retry-after — rate_limited (retry-after без исчерпанного\n * лимита — вторичный лимит частоты GitHub), иначе failed. Тело ответа — без секретов и не длиннее потолка.\n */\nfunction failureOf(url: string, response: Response, raw: string, request: Pick<JsonRequest, 'missing' | 'missingIsIssue' | 'conflictOn'>): TrackerError {\n const status = response.status;\n if (status === 404 && request.missing !== undefined) return new TrackerError(request.missing.failure, request.missing.message);\n if (status === 404 && request.missingIsIssue === true) return new TrackerError('unknown_issue', 'Задача не найдена в трекере.');\n const detail = redactSecretText(raw.replace(/\\s+/g, ' ').trim()).slice(0, TRACKER_ERROR_BODY_MAX);\n const answered = `Трекер ${hostOf(url)} ответил ${String(status)}${detail === '' ? '' : `: ${detail}`}.`;\n if (request.conflictOn?.includes(status) === true) return new TrackerError('conflict', answered);\n const secondaryLimit = status === 403 && (response.headers.get('x-ratelimit-remaining')?.trim() === '0' || retryAfterOf(response.headers.get('retry-after')?.trim(), Date.now()) !== undefined);\n if (status === 429 || secondaryLimit) {\n const delay = retryDelayOf(response.headers);\n return new TrackerError('rate_limited', `Трекер ${hostOf(url)} ограничил частоту запросов${delay === undefined ? '' : `, повтор через ${String(delay)} с`}.`);\n }\n return new TrackerError('failed', answered);\n}\n\n/**\n * Через сколько секунд повторить: retry-after (секунды или HTTP-дата), иначе x-ratelimit-reset (GitHub, epoch секунд),\n * иначе ratelimit-reset (GitLab); не разобралось — undefined.\n */\nfunction retryDelayOf(headers: Headers, now: number = Date.now()): number | undefined {\n const retryAfter = retryAfterOf(headers.get('retry-after')?.trim(), now);\n if (retryAfter !== undefined) return retryAfter;\n for (const name of ['x-ratelimit-reset', 'ratelimit-reset']) {\n const reset = headers.get(name)?.trim();\n if (reset !== undefined && /^\\d+$/.test(reset)) return resetDelay(Number(reset), now);\n }\n return undefined;\n}\n\n/** retry-after — число секунд или HTTP-дата; пустой и неразборчивый — undefined. */\nfunction retryAfterOf(value: string | undefined, now: number): number | undefined {\n if (value === undefined || value === '') return undefined;\n if (/^\\d+$/.test(value)) return Number(value);\n const at = Date.parse(value);\n return Number.isFinite(at) ? Math.max(0, Math.ceil((at - now) / 1000)) : undefined;\n}\n\n/** Сброс лимита: epoch секунд (от 1e9, 2001-09-09) — задержка до него от now; меньшее число — уже задержка в секундах. */\nfunction resetDelay(reset: number, now: number): number {\n return reset >= 1_000_000_000 ? Math.max(0, reset - Math.floor(now / 1000)) : reset;\n}\n\n/** Адрес без пути и параметров: в тексте ошибки секретам неоткуда взяться. */\nfunction hostOf(url: string): string {\n try {\n return new URL(url).host;\n } catch {\n return 'трекер';\n }\n}\n\n/** Базовый адрес без хвостовых слэшей; не http и не https — отказ подключения. */\nexport function baseUrl(value: string | undefined, fallback: string): string {\n const raw = (value ?? fallback).replace(/\\/+$/, '');\n let parsed: URL;\n try {\n parsed = new URL(raw);\n } catch {\n throw new TrackerError('invalid_request', 'Адрес трекера — не URL.');\n }\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') throw new TrackerError('invalid_request', 'Адрес трекера должен быть http или https.');\n return raw;\n}\n","// Реестр трекеров библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/registry.lib.ts — дословная копия. Побочных эффектов при импорте нет:\n// реестр пуст, наполняется только явными вызовами registerTracker/registerBuiltinTrackers (R-001).\nimport type { TrackerDefinition } from './tracker.types.ts';\n\n// Реестр трекеров (D-350): вид подключения → определение. Потребитель работает только через него;\n// новый трекер — модуль с `TrackerDefinition` и одна строка регистрации в `builtin.lib.ts`.\n\nconst definitions = new Map<string, TrackerDefinition>();\n\n/** Регистрирует трекер; повтор того же вида — ошибка сборки, а не замена. */\nexport function registerTracker(definition: TrackerDefinition): void {\n const kind = definition.descriptor.tracker;\n if (definitions.has(kind)) throw new Error(`Трекер ${kind} уже зарегистрирован.`);\n definitions.set(kind, definition);\n}\n\nexport function findTracker(kind: string): TrackerDefinition | undefined {\n return definitions.get(kind);\n}\n\nexport function listTrackers(): TrackerDefinition[] {\n return [...definitions.values()];\n}\n","// Схемы zod pull request-ов единой модели библиотеки @smwb/onreel-git-mcp — свои (#15).\n// Выведенные типы — здесь же (фасет schema, pet:D-037).\nimport { z } from 'zod';\nimport { issueLinkSchema, timestampSchema } from '../contract/contract.schema.ts';\n\n/** Категория состояния PR единой модели (D-005); своё имя трекер отдаёт в status.name. */\nexport const pullRequestStatusCategorySchema = z.enum(['draft', 'open', 'merged', 'closed']);\nexport const pullRequestFilterSchema = z.enum(['status', 'author', 'source', 'target', 'labels', 'search', 'createdAfter', 'createdBefore', 'updatedAfter', 'updatedBefore']);\nexport const pullRequestSortFieldSchema = z.enum(['created', 'updated', 'title']);\nexport const mergeMethodSchema = z.enum(['merge', 'squash', 'rebase']);\n\nexport const pullRequestSchema = z.object({\n /** Номер PR в своём трекере: GitHub number, GitLab iid, SourceCraft slug; для клиента непрозрачная строка. */\n key: z.string().min(1).max(200),\n title: z.string().min(1).max(1024),\n description: z.string().max(1_048_576).optional(),\n status: z.object({ category: pullRequestStatusCategorySchema, name: z.string().min(1).max(200) }),\n /** Автор — логин или slug трекера. */\n author: z.string().min(1).max(200).optional(),\n /** Ветка-источник и целевая ветка — имя без refs/heads/. */\n source: z.string().min(1).max(500),\n target: z.string().min(1).max(500),\n /** Коммит головы источника. */\n headSha: z.string().regex(/^[0-9a-f]{7,64}$/).optional(),\n labels: z.array(z.string().min(1).max(200)).max(100),\n /** Запрошенные ревьюеры; нет — трекер их в PR не отдаёт. */\n reviewers: z.array(z.string().min(1).max(200)).max(100).optional(),\n links: z.array(issueLinkSchema).max(100),\n createdAt: timestampSchema.optional(),\n updatedAt: timestampSchema.optional(),\n mergedAt: timestampSchema.optional(),\n closedAt: timestampSchema.optional(),\n});\n\nexport type PullRequestStatusCategory = z.infer<typeof pullRequestStatusCategorySchema>;\nexport type PullRequestFilter = z.infer<typeof pullRequestFilterSchema>;\nexport type PullRequestSortField = z.infer<typeof pullRequestSortFieldSchema>;\nexport type MergeMethod = z.infer<typeof mergeMethodSchema>;\nexport type PullRequest = z.infer<typeof pullRequestSchema>;\n","// Адаптер pull request-ов GitHub библиотеки @smwb/onreel-git-mcp — свой (#15): раздел pulls определения\n// трекера (D-005) на том же подключении, что и задачи; PR репозитория `owner/repo` через REST API.\nimport type { IssueComment } from '../contract/contract.types.ts';\nimport { baseUrl, requestJson } from './http.lib.ts';\nimport { pullRequestFilterSchema, pullRequestStatusCategorySchema } from './pull.schema.ts';\nimport type { PullRequest, PullRequestStatusCategory } from './pull.schema.ts';\nimport type { MergeInput, NewPullRequestInput, PullRequestAdapter, PullRequestCapabilities, PullRequestDefinition, PullRequestPatchInput, PullRequestQuery } from './pull.types.ts';\nimport { COMMENT_FILTERS } from './tracker.const.ts';\nimport { TrackerError, assertCommentQuery, assertListQuery, containsText, inTimeRange, isRecord, isoTime, requireTarget, stringList, text, toTimestamp } from './tracker.lib.ts';\nimport type { AdapterContext } from './tracker.types.ts';\n\n// Список PR идёт через `/pulls`: параметров автора, меток, поиска и времени у него нет, поэтому эти фильтры\n// проверяются по полученной странице (D-004). Черновик и «готов» переводятся только GraphQL, а ветка-источник\n// при слиянии не удаляется — отказы по capability до записи, снятие черновика — после чтения PR. Комментарии PR лежат под\n// задачиным `/issues/{n}/comments`, а не под `/pulls`.\n\nconst DEFAULT_API = 'https://api.github.com';\nconst TARGET = /^[\\w.-]+\\/[\\w.-]+$/;\nconst NUMBER = /^[1-9]\\d{0,19}$/;\nconst SHA = /^[0-9a-f]{7,64}$/;\nconst LIST_SUBJECT = 'PR GitHub';\nconst COMMENTS_SUBJECT = 'Комментарии PR GitHub';\n\n/** Возможности PR GitHub (§3.6): автор, метки, поиск и время — по странице; сортировка — created и updated. */\nconst PULL_CAPABILITIES: PullRequestCapabilities = {\n list: {\n filters: pullRequestFilterSchema.options,\n clientSide: ['status', 'author', 'labels', 'search', 'createdAfter', 'createdBefore', 'updatedAfter', 'updatedBefore'],\n sorts: ['created', 'updated'],\n },\n comments: { filters: COMMENT_FILTERS, clientSide: [], order: ['asc'] },\n create: true,\n createDraft: true,\n update: ['title', 'description', 'target'],\n statuses: ['open', 'closed'],\n comment: true,\n merge: ['merge', 'squash', 'rebase'],\n deleteSourceOnMerge: false,\n};\n\nexport function githubPulls(): PullRequestDefinition {\n return {\n capabilities: PULL_CAPABILITIES,\n create: (context) => createGithubPullAdapter(context),\n };\n}\n\nfunction createGithubPullAdapter({ connection, fetch }: AdapterContext): PullRequestAdapter {\n const target = requireTarget(connection.target, 'owner/repo репозитория GitHub');\n if (!TARGET.test(target)) throw new TrackerError('invalid_request', 'target GitHub — owner/repo.');\n const api = baseUrl(connection.url, DEFAULT_API);\n const root = `${api}/repos/${target}/pulls`;\n const issues = `${api}/repos/${target}/issues`;\n // `head` списка — `owner:ветка`: источник ищется в том же владельце, что и целевой репозиторий.\n const owner = target.split('/')[0] ?? target;\n const headers = {\n accept: 'application/vnd.github+json',\n 'x-github-api-version': '2022-11-28',\n ...(connection.token === undefined || connection.token === '' ? {} : { authorization: `Bearer ${connection.token}` }),\n };\n const missing = (key: string): { failure: 'not_found'; message: string } => ({ failure: 'not_found', message: `В GitHub нет PR ${key}.` });\n const number = (key: string): string => {\n if (!NUMBER.test(key)) throw new TrackerError('not_found', `В GitHub нет PR ${key}.`);\n return key;\n };\n const getPull = async (key: string): Promise<PullRequest> =>\n pullOf((await requestJson(`${root}/${number(key)}`, { fetch, headers, missing: missing(key) })).body);\n return {\n list: async (query) => {\n assertListQuery(LIST_SUBJECT, PULL_CAPABILITIES.list, query, pullRequestFilterSchema.options);\n const status = usedStatuses(query.status);\n const page = pageOf(query.cursor);\n const params = new URLSearchParams({ state: stateFilter(status), per_page: String(query.limit), page: String(page) });\n if (query.source !== undefined) params.set('head', `${owner}:${query.source}`);\n if (query.target !== undefined) params.set('base', query.target);\n if (query.sort !== undefined) {\n params.set('sort', query.sort.field);\n params.set('direction', query.sort.direction ?? 'desc');\n }\n const { body, headers: responseHeaders } = await requestJson(`${root}?${params.toString()}`, { fetch, headers });\n const items = (Array.isArray(body) ? body : []).map(pullOf).filter((pull) => matchesPage(pull, query, status));\n return { items, ...nextOf(responseHeaders.get('link'), page) };\n },\n get: (key) => getPull(key),\n create: async (input) => pullOf((await requestJson(root, { fetch, headers, method: 'POST', body: createBody(input) })).body),\n update: async (key, patch) => {\n // Черновик через REST не ставится; снятие черновика — тем более, и оно требует текущего состояния PR.\n if (patch.status === 'draft') throw new TrackerError('unsupported', 'PR GitHub: перевод в черновик недоступен через REST.');\n const current = patch.status === 'open' ? await getPull(key) : undefined;\n if (current?.status.category === 'draft') throw new TrackerError('unsupported', 'PR GitHub: снятие черновика недоступно через REST.');\n // Переход «в то же состояние» без других правок не пишет повторно: open на открытом PR — только GET.\n if (current !== undefined && current.status.category === 'open' && patch.title === undefined && patch.description === undefined && patch.target === undefined) return current;\n return pullOf((await requestJson(`${root}/${number(key)}`, { fetch, headers, method: 'PATCH', body: patchBody(patch), missing: missing(key) })).body);\n },\n merge: async (key, input) => {\n if (input.deleteSource === true) throw new TrackerError('unsupported', 'PR GitHub: удаление ветки-источника при слиянии недоступно.');\n if (input.method !== undefined && !PULL_CAPABILITIES.merge.includes(input.method)) {\n throw new TrackerError('unsupported', `PR GitHub: слияние способом ${input.method} не поддерживается.`);\n }\n // Ответ `/merge` — про слияние, а не про PR: состояние перечитывается get-ом.\n await requestJson(`${root}/${number(key)}/merge`, { fetch, headers, method: 'PUT', body: mergeBody(input), conflictOn: [405, 409], missing: missing(key) });\n return getPull(key);\n },\n comments: async (key, query) => {\n assertCommentQuery(COMMENTS_SUBJECT, PULL_CAPABILITIES.comments, query);\n const page = pageOf(query.cursor);\n const params = new URLSearchParams({ per_page: String(query.limit), page: String(page) });\n // `since` — изменения не раньше момента; порядок у GitHub один, по id (§3.7 B2).\n if (query.updatedAfter !== undefined) params.set('since', isoTime(query.updatedAfter));\n const { body, headers: responseHeaders } = await requestJson(`${issues}/${number(key)}/comments?${params.toString()}`, { fetch, headers, missing: missing(key) });\n return { items: (Array.isArray(body) ? body : []).map(commentOf), ...nextOf(responseHeaders.get('link'), page) };\n },\n comment: async (key, body) => commentOf((await requestJson(`${issues}/${number(key)}/comments`, { fetch, headers, method: 'POST', body: { body }, missing: missing(key) })).body),\n };\n}\n\nfunction pageOf(cursor: string | undefined): number {\n const page = cursor === undefined ? 1 : Number(cursor);\n return Number.isInteger(page) && page >= 1 ? page : 1;\n}\n\n/** Следующая страница по `Link`; курсор — номер страницы (§1.1). */\nfunction nextOf(link: string | null, page: number): { nextCursor?: string } {\n return link !== null && /rel=\"next\"/.test(link) ? { nextCursor: String(page + 1) } : {};\n}\n\n/** Категории состояния → `state` списка: черновик и открытый — open, слитый и закрытый — closed;\n * смешанный запрос — all, лишнее отсеет страница. */\nfunction stateFilter(status: readonly PullRequestStatusCategory[] | undefined): string {\n if (status === undefined) return 'all';\n if (status.every((item) => item === 'draft' || item === 'open')) return 'open';\n if (status.every((item) => item === 'merged' || item === 'closed')) return 'closed';\n return 'all';\n}\n\n/** Фильтры, которых нет в параметрах `/pulls`: категория (черновик и слитый видны только по полям PR),\n * автор, метки, поиск и границы времени — по полученной странице (D-004, §3.7 B2). */\nfunction matchesPage(pull: PullRequest, query: PullRequestQuery, status: readonly PullRequestStatusCategory[] | undefined): boolean {\n if (status !== undefined && !status.includes(pull.status.category)) return false;\n if (query.author !== undefined && pull.author !== query.author) return false;\n if (query.labels !== undefined && !query.labels.every((label) => pull.labels.includes(label))) return false;\n if (query.search !== undefined && !containsText([pull.title, pull.description], query.search)) return false;\n return inTimeRange(pull.createdAt, query.createdAfter, query.createdBefore) && inTimeRange(pull.updatedAt, query.updatedAfter, query.updatedBefore);\n}\n\n/** Статусы списка: пустой массив — без фильтра; неизвестная категория — invalid_request до запроса. */\nfunction usedStatuses(status: readonly PullRequestStatusCategory[] | undefined): readonly PullRequestStatusCategory[] | undefined {\n if (status === undefined || status.length === 0) return undefined;\n for (const item of status) {\n if (!pullRequestStatusCategorySchema.options.includes(item)) {\n throw new TrackerError('invalid_request', `PR GitHub: неизвестная категория статуса ${String(item)}.`);\n }\n }\n return status;\n}\n\n/** Тело создания PR: `head` — ветка источника своего репозитория, черновик ставится только когда запрошен. */\nfunction createBody(input: NewPullRequestInput): Record<string, unknown> {\n return {\n title: input.title,\n head: input.source,\n base: input.target,\n ...(input.description === undefined ? {} : { body: input.description }),\n ...(input.draft === true ? { draft: true } : {}),\n };\n}\n\n/** Тело PATCH: поля правки плюс переход состояния — open или closed, черновик отсекается выше. */\nfunction patchBody(patch: PullRequestPatchInput): Record<string, unknown> {\n return {\n ...(patch.title === undefined ? {} : { title: patch.title }),\n ...(patch.description === undefined ? {} : { body: patch.description }),\n ...(patch.target === undefined ? {} : { base: patch.target }),\n ...(patch.status === undefined ? {} : { state: patch.status === 'closed' ? 'closed' : 'open' }),\n };\n}\n\n/** Тело слияния: способ, ожидаемая голова и сообщение коммита — первая строка заголовок, остальное текст. */\nfunction mergeBody(input: MergeInput): Record<string, unknown> {\n const lines = input.message?.split('\\n') ?? [];\n return {\n ...(input.method === undefined ? {} : { merge_method: input.method }),\n ...(input.headSha === undefined ? {} : { sha: input.headSha }),\n ...(input.message === undefined ? {} : { commit_title: lines[0] ?? '' }),\n ...(lines.length > 1 ? { commit_message: lines.slice(1).join('\\n') } : {}),\n };\n}\n\nfunction pullOf(raw: unknown): PullRequest {\n const item = isRecord(raw) ? raw : {};\n const head = isRecord(item.head) ? item.head : {};\n const base = isRecord(item.base) ? item.base : {};\n const key = typeof item.number === 'number' ? String(item.number) : '?';\n const description = text(item.body);\n const author = isRecord(item.user) ? text(item.user.login) : undefined;\n const sha = text(head.sha);\n const url = text(item.html_url);\n const createdAt = toTimestamp(item.created_at);\n const updatedAt = toTimestamp(item.updated_at);\n const mergedAt = toTimestamp(item.merged_at);\n const closedAt = toTimestamp(item.closed_at);\n const closed = item.state === 'closed';\n const merged = item.merged_at !== undefined && item.merged_at !== null;\n // Состояние PR: слитый закрыт вместе с merged_at, черновик — открытый со своим флагом.\n const category: PullRequestStatusCategory = closed ? merged ? 'merged' : 'closed' : item.draft === true ? 'draft' : 'open';\n return {\n key,\n title: text(item.title) ?? key,\n ...(description === undefined ? {} : { description }),\n status: { category, name: category },\n ...(author === undefined ? {} : { author }),\n source: text(head.ref) ?? '?',\n target: text(base.ref) ?? '?',\n ...(sha !== undefined && SHA.test(sha) ? { headSha: sha } : {}),\n labels: Array.isArray(item.labels) ? stringList(item.labels.map((label) => (isRecord(label) ? label.name : label))) : [],\n reviewers: logins(item.requested_reviewers),\n links: url === undefined ? [] : [{ url, title: 'GitHub' }],\n ...(createdAt === undefined ? {} : { createdAt }),\n ...(updatedAt === undefined ? {} : { updatedAt }),\n ...(mergedAt === undefined ? {} : { mergedAt }),\n ...(closedAt === undefined ? {} : { closedAt }),\n };\n}\n\n/** Логины запрошенных ревьюеров: GitHub отдаёт их массивом объектов. */\nfunction logins(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n const names = value.map((item) => (isRecord(item) ? text(item.login) : undefined));\n return [...new Set(names.filter((name): name is string => name !== undefined))];\n}\n\nfunction commentOf(raw: unknown): IssueComment {\n const item = isRecord(raw) ? raw : {};\n const author = isRecord(item.user) ? text(item.user.login) : undefined;\n const createdAt = toTimestamp(item.created_at);\n return { id: typeof item.id === 'number' ? String(item.id) : '?', ...(author === undefined ? {} : { author }), body: typeof item.body === 'string' ? item.body : '', ...(createdAt === undefined ? {} : { createdAt }) };\n}\n","// Адаптер GitHub библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/github.lib.ts — дословная копия, импорт типов из среза контракта библиотеки;\n// возможности фильтров, маршрутизация /issues ↔ Search API и since комментариев — свои (#14).\nimport type { Issue, IssueComment, IssuePriority, IssueStatusCategory } from '../contract/contract.types.ts';\nimport { githubPulls } from './github-pull.lib.ts';\nimport { baseUrl, requestJson } from './http.lib.ts';\nimport { GITHUB_CLOSE_REASONS, GITHUB_IN_PROGRESS_LABEL, GITHUB_PRIORITY_LABELS } from './mapping.const.ts';\nimport { ISSUE_FILTERS } from './tracker.const.ts';\nimport { TrackerError, assertCommentQuery, assertListQuery, isRecord, isoTime, lookup, priorityName, quoted, requireTarget, stringList, text, toTimestamp } from './tracker.lib.ts';\nimport type { AdapterContext, IssueCapabilities, IssuePatchInput, IssueQuery, TrackerAdapter, TrackerDefinition, TrackerPage } from './tracker.types.ts';\n\n// Трекер GitHub (D-350): задачи репозитория `owner/repo` через REST API. У GitHub статус — open или closed\n// с причиной: «в работе» держится меткой `in progress`, приоритет — меткой `priority: <имя>`; обе метки\n// читаются в поля единой модели и из `labels` убираются. Pull request-ы в списке задач пропускаются.\n// Список идёт через `/issues`, а поиск по тексту и границы created/updated-before есть только в Search API (#14).\n\nconst DEFAULT_API = 'https://api.github.com';\nconst TARGET = /^[\\w.-]+\\/[\\w.-]+$/;\nconst NUMBER = /^[1-9]\\d{0,14}$/;\nconst LIST_SUBJECT = 'Задачи GitHub';\nconst COMMENTS_SUBJECT = 'Комментарии GitHub';\n\nexport function githubTracker(): TrackerDefinition {\n // Возможности по задачам (§3.6): статус GitHub не фильтрует, поэтому проверяется по полученной странице;\n // комментарии — только по времени изменения и только в порядке asc.\n const issues: IssueCapabilities = {\n list: { filters: ISSUE_FILTERS, clientSide: ['status'], sorts: ['created', 'updated', 'comments'] },\n comments: { filters: ['updatedAfter'], clientSide: [], order: ['asc'] },\n };\n return {\n descriptor: {\n tracker: 'github',\n title: 'GitHub',\n fields: [\n { name: 'target', required: true, secret: false },\n { name: 'token', required: true, secret: true },\n { name: 'url', required: false, secret: false },\n ],\n features: { create: true, update: true, comment: true, priority: true, labels: true, assignee: true, statuses: ['open', 'in_progress', 'done', 'declined'] },\n },\n create: (context) => createGithubAdapter(context, issues),\n issues,\n pulls: githubPulls(),\n };\n}\n\nfunction createGithubAdapter({ connection, fetch }: AdapterContext, capabilities: IssueCapabilities): TrackerAdapter {\n const target = requireTarget(connection.target, 'owner/repo репозитория GitHub');\n if (!TARGET.test(target)) throw new TrackerError('invalid_request', 'target GitHub — owner/repo.');\n const api = baseUrl(connection.url, DEFAULT_API);\n const root = `${api}/repos/${target}/issues`;\n const headers = {\n accept: 'application/vnd.github+json',\n 'x-github-api-version': '2022-11-28',\n ...(connection.token === undefined || connection.token === '' ? {} : { authorization: `Bearer ${connection.token}` }),\n };\n const number = (key: string): string => {\n if (!NUMBER.test(key)) throw new TrackerError('unknown_issue', `В GitHub нет задачи ${key}.`);\n return key;\n };\n const rawOf = async (key: string): Promise<Record<string, unknown>> => {\n const { body } = await requestJson(`${root}/${number(key)}`, { fetch, headers, missingIsIssue: true });\n return isRecord(body) ? body : {};\n };\n return {\n list: async (query) => {\n assertListQuery(LIST_SUBJECT, capabilities.list, query, ISSUE_FILTERS);\n assertCsvLabels(query.labels);\n const page = pageOf(query.cursor);\n // Search API нужен, когда запрошено то, чего `/issues` не умеет: текст поиска и границы created/updated-before (§3.7 A2).\n const search = needsSearch(query);\n const params = search ? searchParams(target, query, page) : issuesParams(query, page);\n const { body, headers: responseHeaders } = await requestJson(`${search ? `${api}/search/issues` : root}?${params.toString()}`, { fetch, headers });\n return issuePageOf(rowsOf(body, search), query, responseHeaders.get('link') ?? '', page);\n },\n get: async (key) => issueOf(await rawOf(key)),\n create: async (input) => {\n const labels = composeLabels(input.labels ?? [], input.priority, undefined);\n const body = {\n title: input.title,\n ...(input.description === undefined ? {} : { body: input.description }),\n ...(labels.length === 0 ? {} : { labels }),\n ...(input.assignee === undefined ? {} : { assignees: [input.assignee] }),\n };\n return issueOf((await requestJson(root, { fetch, headers, method: 'POST', body })).body);\n },\n update: async (key, patch) => {\n const current = patch.labels === undefined && patch.priority === undefined && patch.status === undefined ? undefined : issueOf(await rawOf(key));\n const response = await requestJson(`${root}/${number(key)}`, { fetch, headers, method: 'PATCH', body: patchBody(patch, current), missingIsIssue: true });\n return issueOf(response.body);\n },\n comments: async (key, query) => {\n assertCommentQuery(COMMENTS_SUBJECT, capabilities.comments, query);\n const page = pageOf(query.cursor);\n const params = new URLSearchParams({ per_page: String(query.limit), page: String(page) });\n // `since` — изменения не раньше момента; порядок у GitHub один, по id (§3.7 A2).\n if (query.updatedAfter !== undefined) params.set('since', isoTime(query.updatedAfter));\n const { body, headers: responseHeaders } = await requestJson(`${root}/${number(key)}/comments?${params.toString()}`, { fetch, headers, missingIsIssue: true });\n return { items: (Array.isArray(body) ? body : []).map(commentOf), ...(/rel=\"next\"/.test(responseHeaders.get('link') ?? '') ? { nextCursor: String(page + 1) } : {}) };\n },\n comment: async (key, body) => commentOf((await requestJson(`${root}/${number(key)}/comments`, { fetch, headers, method: 'POST', body: { body }, missingIsIssue: true })).body),\n };\n}\n\nfunction pageOf(cursor: string | undefined): number {\n const page = cursor === undefined ? 1 : Number(cursor);\n return Number.isInteger(page) && page >= 1 ? page : 1;\n}\n\n/** Параметр `state` по запрошенным категориям; смешанный запрос — все, лишнее отсеет клиент. */\nfunction stateFilter(status: readonly IssueStatusCategory[] | undefined): string {\n if (status === undefined) return 'all';\n if (status.every((item) => item === 'open' || item === 'in_progress')) return 'open';\n if (status.every((item) => item === 'done' || item === 'declined')) return 'closed';\n return 'all';\n}\n\n/** Поиск по тексту и границы created/updated-before есть только в Search API — он и выбирает endpoint (§3.7 A2). */\nfunction needsSearch(query: IssueQuery): boolean {\n return query.search !== undefined || query.createdAfter !== undefined || query.createdBefore !== undefined || query.updatedBefore !== undefined;\n}\n\n/** CSV-параметр labels: запятая внутри метки читалась бы как разделитель списка — отказ до запроса (§3.2 R1). */\nfunction assertCsvLabels(labels: readonly string[] | undefined): void {\n if (labels?.some((label) => label.includes(',')) === true) throw new TrackerError('invalid_request', `${LIST_SUBJECT}: метка не должна содержать запятую.`);\n}\n\n/** Параметры `/issues`: сегодняшние плюс фильтры и сортировка, которые GitHub применяет сам. */\nfunction issuesParams(query: IssueQuery, page: number): URLSearchParams {\n const params = new URLSearchParams({ state: stateFilter(query.status), per_page: String(query.limit), page: String(page) });\n if (query.labels !== undefined && query.labels.length > 0) params.set('labels', query.labels.join(','));\n if (query.assignee !== undefined) params.set('assignee', query.assignee ?? 'none');\n if (query.author !== undefined) params.set('creator', query.author);\n if (query.updatedAfter !== undefined) params.set('since', isoTime(query.updatedAfter));\n if (query.sort !== undefined) {\n params.set('sort', query.sort.field);\n params.set('direction', query.sort.direction ?? 'desc');\n }\n return params;\n}\n\n/** Параметры поиска: `q` плюс страницы и сортировка с `order` вместо `direction`; без sort — created desc,\n * иначе GitHub сортирует по релевантности, а порядок по умолчанию у списка — новые первыми (§3.2 R4, §3.7 A2). */\nfunction searchParams(target: string, query: IssueQuery, page: number): URLSearchParams {\n const params = new URLSearchParams({ q: searchQuery(target, query), per_page: String(query.limit), page: String(page) });\n const sort = query.sort;\n params.set('sort', sort?.field ?? 'created');\n params.set('order', sort?.direction ?? 'desc');\n return params;\n}\n\n/** `q` поиска: репозиторий и тип, затем фильтры; свободный текст — одна фраза в кавычках (§3.2 R6). */\nfunction searchQuery(target: string, query: IssueQuery): string {\n const parts: string[] = [`repo:${target}`, 'is:issue'];\n const state = searchStateFilter(query.status);\n if (state !== undefined) parts.push(state);\n for (const label of query.labels ?? []) parts.push(`label:${quoted(label)}`);\n if (query.assignee !== undefined) parts.push(query.assignee === null ? 'no:assignee' : `assignee:${quoted(query.assignee)}`);\n if (query.author !== undefined) parts.push(`author:${quoted(query.author)}`);\n const created = timeRangeQualifier('created', query.createdAfter, query.createdBefore);\n if (created !== undefined) parts.push(created);\n const updated = timeRangeQualifier('updated', query.updatedAfter, query.updatedBefore);\n if (updated !== undefined) parts.push(updated);\n if (query.search !== undefined) parts.push(quoted(query.search));\n return parts.join(' ');\n}\n\n/** Границы поля времени в q: обе — один квалификатор-диапазон (два квалификатора GitHub объединяет через OR),\n * одна — >= / <=. ISO без кавычек: значение машинное ([0-9TZ:.-]), квалификатор из него не вставить (§3.2 R6). */\nfunction timeRangeQualifier(field: 'created' | 'updated', after: number | undefined, before: number | undefined): string | undefined {\n if (after !== undefined && before !== undefined) return `${field}:${isoTime(after)}..${isoTime(before)}`;\n if (after !== undefined) return `${field}:>=${isoTime(after)}`;\n if (before !== undefined) return `${field}:<=${isoTime(before)}`;\n return undefined;\n}\n\n/** Элементы ответа: `/issues` отдаёт массив, поиск — объект с `items` (§3.7 A2). */\nfunction rowsOf(body: unknown, search: boolean): readonly unknown[] {\n if (!search) return Array.isArray(body) ? body : [];\n return isRecord(body) && Array.isArray(body.items) ? body.items : [];\n}\n\n/** `is:open`/`is:closed` по запрошенным категориям; смешанный запрос — без него, лишнее отсеет страница. */\nfunction searchStateFilter(status: readonly IssueStatusCategory[] | undefined): string | undefined {\n if (status === undefined) return undefined;\n if (status.every((item) => item === 'open' || item === 'in_progress')) return 'is:open';\n if (status.every((item) => item === 'done' || item === 'declined')) return 'is:closed';\n return undefined;\n}\n\n/** Страница задач: pull request-ы пропускаются, статус сверяется с полученной страницей (§3.2 R5). */\nfunction issuePageOf(rows: readonly unknown[], query: IssueQuery, link: string, page: number): TrackerPage<Issue> {\n const items = rows.filter((row) => isRecord(row) && row.pull_request === undefined).map(issueOf);\n return {\n items: query.status === undefined ? items : items.filter((issue) => query.status?.includes(issue.status.category) === true),\n ...(/rel=\"next\"/.test(link) ? { nextCursor: String(page + 1) } : {}),\n };\n}\n\n/** Метки записи: пользовательские плюс служебные для приоритета и «в работе». */\nfunction composeLabels(plain: readonly string[], priority: IssuePriority | undefined, status: IssueStatusCategory | undefined): string[] {\n const priorityLabel = priority === undefined ? undefined : priorityName(GITHUB_PRIORITY_LABELS, priority);\n return [...plain, ...(priorityLabel === undefined ? [] : [priorityLabel]), ...(status === 'in_progress' ? [GITHUB_IN_PROGRESS_LABEL] : [])];\n}\n\nfunction patchBody(patch: IssuePatchInput, current: Issue | undefined): Record<string, unknown> {\n const status = patch.status ?? current?.status.category;\n const touchesLabels = patch.labels !== undefined || patch.priority !== undefined || patch.status !== undefined;\n return {\n ...(patch.title === undefined ? {} : { title: patch.title }),\n ...(patch.description === undefined ? {} : { body: patch.description }),\n ...(patch.status === undefined ? {} : { state: patch.status === 'done' || patch.status === 'declined' ? 'closed' : 'open', ...(patch.status === 'declined' ? { state_reason: 'not_planned' } : patch.status === 'done' ? { state_reason: 'completed' } : { state_reason: 'reopened' }) }),\n ...(touchesLabels ? { labels: composeLabels(patch.labels ?? current?.labels ?? [], patch.priority ?? current?.priority, status) } : {}),\n ...(patch.assignee === undefined ? {} : { assignees: patch.assignee === null ? [] : [patch.assignee] }),\n };\n}\n\nfunction issueOf(raw: unknown): Issue {\n const item = isRecord(raw) ? raw : {};\n const names = Array.isArray(item.labels) ? stringList(item.labels.map((label) => (isRecord(label) ? label.name : label))) : [];\n const closed = item.state === 'closed';\n const category: IssueStatusCategory = closed ? lookup(GITHUB_CLOSE_REASONS, item.state_reason, 'done') : names.includes(GITHUB_IN_PROGRESS_LABEL) ? 'in_progress' : 'open';\n const priority = names.map((name) => lookup<IssuePriority | undefined>(GITHUB_PRIORITY_LABELS, name, undefined)).find((value) => value !== undefined);\n const description = text(item.body);\n const assignee = isRecord(item.assignee) ? text(item.assignee.login) : undefined;\n const url = text(item.html_url);\n const createdAt = toTimestamp(item.created_at);\n const updatedAt = toTimestamp(item.updated_at);\n const number = typeof item.number === 'number' ? String(item.number) : '?';\n return {\n key: number,\n title: text(item.title) ?? number,\n ...(description === undefined ? {} : { description }),\n status: { category, name: closed ? `closed${typeof item.state_reason === 'string' ? ` (${item.state_reason})` : ''}` : category === 'in_progress' ? 'in progress' : 'open' },\n ...(priority === undefined ? {} : { priority }),\n labels: names.filter((name) => name !== GITHUB_IN_PROGRESS_LABEL && !Object.hasOwn(GITHUB_PRIORITY_LABELS, name)),\n ...(assignee === undefined ? {} : { assignee }),\n links: url === undefined ? [] : [{ url, title: 'GitHub' }],\n ...(createdAt === undefined ? {} : { createdAt }),\n ...(updatedAt === undefined ? {} : { updatedAt }),\n };\n}\n\nfunction commentOf(raw: unknown): IssueComment {\n const item = isRecord(raw) ? raw : {};\n const author = isRecord(item.user) ? text(item.user.login) : undefined;\n const createdAt = toTimestamp(item.created_at);\n return { id: typeof item.id === 'number' ? String(item.id) : '?', ...(author === undefined ? {} : { author }), body: typeof item.body === 'string' ? item.body : '', ...(createdAt === undefined ? {} : { createdAt }) };\n}\n","// Адаптер merge request-ов GitLab библиотеки @smwb/onreel-git-mcp — свой (#15): раздел pulls\n// определения трекера (D-005) на том же подключении, что и задачи; MR проекта через REST API v4.\nimport type { IssueComment } from '../contract/contract.types.ts';\nimport { baseUrl, requestJson } from './http.lib.ts';\nimport { GITLAB_DRAFT_PATTERN, GITLAB_DRAFT_PREFIX, GITLAB_MERGE_REQUEST_STATES } from './mapping.const.ts';\nimport { pullRequestFilterSchema, pullRequestStatusCategorySchema } from './pull.schema.ts';\nimport type { PullRequest, PullRequestStatusCategory } from './pull.schema.ts';\nimport type { PullRequestAdapter, PullRequestCapabilities, PullRequestDefinition, PullRequestPatchInput } from './pull.types.ts';\nimport { COMMENT_FILTERS } from './tracker.const.ts';\nimport { TrackerError, assertCommentQuery, assertListQuery, inTimeRange, isRecord, isoTime, lookup, requireTarget, text, toTimestamp } from './tracker.lib.ts';\nimport type { AdapterContext } from './tracker.types.ts';\n\n// Черновик у GitLab — префикс заголовка (`Draft: ` и прочие формы), а не поле: draft открытого MR адаптер\n// читает из поля draft, а ставит и снимает правкой заголовка. Слияние rebase — отдельный эндпоинт, которого\n// в единой модели нет.\n\nconst DEFAULT_URL = 'https://gitlab.com';\nconst TARGET = /^(\\d{1,15}|[\\w.-]+(\\/[\\w.-]+)+)$/;\nconst IID = /^[1-9]\\d{0,19}$/;\nconst SHA = /^[0-9a-f]{7,64}$/;\n\n/** Возможности PR GitLab (#15): все фильтры единой модели, статус (включая черновик) проверяется по странице. */\nconst PULL_CAPABILITIES: PullRequestCapabilities = {\n list: { filters: pullRequestFilterSchema.options, clientSide: ['status'], sorts: ['created', 'updated', 'title'] },\n comments: { filters: COMMENT_FILTERS, clientSide: COMMENT_FILTERS, order: ['asc', 'desc'] },\n create: true,\n createDraft: true,\n update: ['title', 'description', 'target'],\n statuses: ['draft', 'open', 'closed'],\n comment: true,\n merge: ['merge', 'squash'],\n deleteSourceOnMerge: true,\n};\n\n/** Поле сортировки единой модели → order_by GitLab. */\nconst ORDER_BY: Readonly<Record<string, string>> = { created: 'created_at', updated: 'updated_at', title: 'title' };\n\nexport function gitlabPulls(): PullRequestDefinition {\n return {\n capabilities: PULL_CAPABILITIES,\n create: (context) => createGitlabPullAdapter(context),\n };\n}\n\nfunction createGitlabPullAdapter({ connection, fetch }: AdapterContext): PullRequestAdapter {\n const target = requireTarget(connection.target, 'путь проекта GitLab, group/project, или его id');\n if (!TARGET.test(target)) throw new TrackerError('invalid_request', 'target GitLab — group/project или числовой id.');\n const root = `${baseUrl(connection.url, DEFAULT_URL)}/api/v4/projects/${encodeURIComponent(target)}/merge_requests`;\n const headers: Record<string, string> = connection.token === undefined || connection.token === '' ? {} : { 'private-token': connection.token };\n const iid = (key: string): string => {\n if (!IID.test(key)) throw new TrackerError('not_found', `В GitLab нет MR ${key}.`);\n return key;\n };\n const currentOf = async (key: string): Promise<PullRequest> => pullOf((await requestJson(`${root}/${iid(key)}`, { fetch, headers, missing: { failure: 'not_found', message: `В GitLab нет MR ${key}.` } })).body);\n return {\n list: async (query) => {\n assertListQuery('PR GitLab', PULL_CAPABILITIES.list, query, pullRequestFilterSchema.options);\n const status = usedStatuses(query.status);\n const page = pageOf(query.cursor);\n const params = new URLSearchParams({\n state: stateFilter(status),\n per_page: String(query.limit),\n page: String(page),\n order_by: query.sort === undefined ? 'created_at' : (ORDER_BY[query.sort.field] ?? 'created_at'),\n sort: query.sort?.direction ?? 'desc',\n });\n if (query.labels !== undefined && query.labels.length > 0) {\n if (query.labels.some((label) => label.includes(','))) throw new TrackerError('invalid_request', 'PR GitLab: метка не должна содержать запятую.');\n params.set('labels', query.labels.join(','));\n }\n if (query.author !== undefined) params.set('author_username', query.author);\n if (query.source !== undefined) params.set('source_branch', query.source);\n if (query.target !== undefined) params.set('target_branch', query.target);\n if (query.search !== undefined) params.set('search', query.search);\n if (query.createdAfter !== undefined) params.set('created_after', isoTime(query.createdAfter));\n if (query.createdBefore !== undefined) params.set('created_before', isoTime(query.createdBefore));\n if (query.updatedAfter !== undefined) params.set('updated_after', isoTime(query.updatedAfter));\n if (query.updatedBefore !== undefined) params.set('updated_before', isoTime(query.updatedBefore));\n const { body, headers: responseHeaders } = await requestJson(`${root}?${params.toString()}`, { fetch, headers });\n const next = responseHeaders.get('x-next-page');\n const items = (Array.isArray(body) ? body : []).map(pullOf);\n // Черновик против открытого адаптер различает по полю draft на странице: страница бывает короче limit.\n return {\n items: status === undefined ? items : items.filter((pr) => status.includes(pr.status.category) === true),\n ...(next === null || next === '' ? {} : { nextCursor: next }),\n };\n },\n get: currentOf,\n create: async (input) => {\n const body = {\n source_branch: input.source,\n target_branch: input.target,\n title: (input.draft === true ? GITLAB_DRAFT_PREFIX : '') + input.title,\n ...(input.description === undefined ? {} : { description: input.description }),\n };\n return pullOf((await requestJson(root, { fetch, headers, method: 'POST', body, conflictOn: [409] })).body);\n },\n update: async (key, patch) => {\n const current = patch.status === undefined ? undefined : await currentOf(key);\n if (patch.status === 'draft' && current?.status.category === 'closed') {\n throw new TrackerError('unsupported', 'PR GitLab: перевод закрытого MR в черновик недоступен.');\n }\n const body = patchBody(patch, current);\n // Пустое тело GitLab отклоняет (400): неизменный запрос — без PUT, ответ — текущий MR.\n if (Object.keys(body).length === 0) return current ?? pullOf((await requestJson(`${root}/${iid(key)}`, { fetch, headers, missing: { failure: 'not_found', message: `В GitLab нет MR ${key}.` } })).body);\n return pullOf((await requestJson(`${root}/${iid(key)}`, { fetch, headers, method: 'PUT', body, missing: { failure: 'not_found', message: `В GitLab нет MR ${key}.` } })).body);\n },\n merge: async (key, input) => {\n if (input.method !== undefined && !PULL_CAPABILITIES.merge.includes(input.method)) {\n throw new TrackerError('unsupported', `PR GitLab: слияние способом ${input.method} не поддерживается.`);\n }\n const body = {\n // squash: true ставит squash; false GitLab игнорирует — при method 'merge' действует настройка MR/проекта.\n ...(input.method === 'squash' ? { squash: true } : {}),\n ...(input.message === undefined ? {} : input.method === 'squash' ? { squash_commit_message: input.message } : { merge_commit_message: input.message }),\n ...(input.deleteSource === undefined ? {} : { should_remove_source_branch: input.deleteSource }),\n ...(input.headSha === undefined ? {} : { sha: input.headSha }),\n };\n return pullOf((await requestJson(`${root}/${iid(key)}/merge`, { fetch, headers, method: 'PUT', body, conflictOn: [405, 409, 422], missing: { failure: 'not_found', message: `В GitLab нет MR ${key}.` } })).body);\n },\n comments: async (key, query) => {\n assertCommentQuery('Комментарии GitLab', PULL_CAPABILITIES.comments, query);\n const page = pageOf(query.cursor);\n const params = new URLSearchParams({ sort: query.order ?? 'asc', order_by: 'created_at', per_page: String(query.limit), page: String(page) });\n const { body, headers: responseHeaders } = await requestJson(`${root}/${iid(key)}/notes?${params.toString()}`, { fetch, headers, missing: { failure: 'not_found', message: `В GitLab нет MR ${key}.` } });\n const next = responseHeaders.get('x-next-page');\n // Системные заметки («изменил метку») — не комментарии; updatedAfter сверяется с сырым updated_at заметки.\n const items = (Array.isArray(body) ? body : [])\n .filter((note) => isRecord(note) && note.system !== true && inTimeRange(toTimestamp(note.updated_at), query.updatedAfter, undefined))\n .map(commentOf);\n return { items, ...(next === null || next === '' ? {} : { nextCursor: next }) };\n },\n comment: async (key, body) => commentOf((await requestJson(`${root}/${iid(key)}/notes`, { fetch, headers, method: 'POST', body: { body }, missing: { failure: 'not_found', message: `В GitLab нет MR ${key}.` } })).body),\n };\n}\n\nfunction pageOf(cursor: string | undefined): number {\n const page = cursor === undefined ? 1 : Number(cursor);\n return Number.isInteger(page) && page >= 1 ? page : 1;\n}\n\n/** Категории состояния → state списка: только черновики и открытые — opened, смешанный набор — all. */\nfunction stateFilter(status: readonly PullRequestStatusCategory[] | undefined): string {\n if (status === undefined) return 'all';\n if (status.every((item) => item === 'draft' || item === 'open')) return 'opened';\n if (status.every((item) => item === 'merged')) return 'merged';\n if (status.every((item) => item === 'closed')) return 'closed';\n return 'all';\n}\n\n/** Тело PUT: поля правки и переход состояния; черновик правится префиксом заголовка, что требует текущего MR.\n * Переход «в то же состояние» не пишет повторно: повторный close и неизменный заголовок опускаются. */\nfunction patchBody(patch: PullRequestPatchInput, current: PullRequest | undefined): Record<string, unknown> {\n const body: Record<string, unknown> = {};\n if (patch.description !== undefined) body.description = patch.description;\n if (patch.target !== undefined) body.target_branch = patch.target;\n if (patch.status === 'closed' && current?.status.category !== 'closed') body.state_event = 'close';\n if (patch.status === 'open' && current?.status.category === 'closed') body.state_event = 'reopen';\n if (patch.status === 'draft' || patch.status === 'open') {\n // Перевод в черновик или снятие черновика: прежние формы префикса снимаются, при черновике — свой префикс;\n // open на закрытом черновике снимает префикс вместе с reopen, чтобы результат был open, а не draft.\n const title = patch.title ?? current?.title ?? '';\n const base = title.replace(GITLAB_DRAFT_PATTERN, '');\n // Неизменный заголовок (draft на черновике, open на открытом) сверяется с текущим MR и не отправляется повторно.\n const next = patch.status === 'draft' ? GITLAB_DRAFT_PREFIX + base : current?.status.category === 'draft' || title !== base ? base : patch.title;\n if (next !== undefined && next !== current?.title) body.title = next;\n } else if (patch.title !== undefined && patch.title !== current?.title) {\n body.title = patch.title;\n }\n return body;\n}\n\n/** Статусы списка: пустой массив — без фильтра; неизвестная категория — invalid_request до запроса. */\nfunction usedStatuses(status: readonly PullRequestStatusCategory[] | undefined): readonly PullRequestStatusCategory[] | undefined {\n if (status === undefined || status.length === 0) return undefined;\n for (const item of status) {\n if (!pullRequestStatusCategorySchema.options.includes(item)) {\n throw new TrackerError('invalid_request', `PR GitLab: неизвестная категория статуса ${String(item)}.`);\n }\n }\n return status;\n}\n\n/** Метки MR: GitLab отдаёт и строки, и объекты с name. */\nfunction labelNames(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n const names = value.map((item) => (typeof item === 'string' ? item : isRecord(item) ? text(item.name) : undefined));\n return [...new Set(names.filter((name): name is string => name !== undefined && name !== ''))];\n}\n\nfunction usernames(value: unknown): string[] {\n if (!Array.isArray(value)) return [];\n const names = value.map((item) => (isRecord(item) ? text(item.username) : undefined));\n return [...new Set(names.filter((name): name is string => name !== undefined && name !== ''))];\n}\n\nfunction pullOf(raw: unknown): PullRequest {\n const item = isRecord(raw) ? raw : {};\n const state = text(item.state) ?? 'opened';\n const draft = item.draft === true;\n const category = lookup<PullRequestStatusCategory>(GITLAB_MERGE_REQUEST_STATES, state, 'open');\n const key = typeof item.iid === 'number' ? String(item.iid) : '?';\n const description = text(item.description);\n const author = isRecord(item.author) ? text(item.author.username) : undefined;\n const sha = text(item.sha);\n const url = text(item.web_url);\n const createdAt = toTimestamp(item.created_at);\n const updatedAt = toTimestamp(item.updated_at);\n const mergedAt = toTimestamp(item.merged_at);\n const closedAt = toTimestamp(item.closed_at);\n return {\n key,\n title: text(item.title) ?? key,\n ...(description === undefined ? {} : { description }),\n status: { category: draft && category === 'open' ? 'draft' : category, name: draft && category === 'open' ? 'draft' : state },\n ...(author === undefined ? {} : { author }),\n source: text(item.source_branch) ?? '?',\n target: text(item.target_branch) ?? '?',\n ...(sha !== undefined && SHA.test(sha) ? { headSha: sha } : {}),\n labels: labelNames(item.labels),\n reviewers: usernames(item.reviewers),\n links: url === undefined ? [] : [{ url, title: 'GitLab' }],\n ...(createdAt === undefined ? {} : { createdAt }),\n ...(updatedAt === undefined ? {} : { updatedAt }),\n ...(mergedAt === undefined ? {} : { mergedAt }),\n ...(closedAt === undefined ? {} : { closedAt }),\n };\n}\n\nfunction commentOf(raw: unknown): IssueComment {\n const item = isRecord(raw) ? raw : {};\n const author = isRecord(item.author) ? text(item.author.username) : undefined;\n const createdAt = toTimestamp(item.created_at);\n return { id: typeof item.id === 'number' ? String(item.id) : '?', ...(author === undefined ? {} : { author }), body: typeof item.body === 'string' ? item.body : '', ...(createdAt === undefined ? {} : { createdAt }) };\n}\n","// Адаптер GitLab библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/gitlab.lib.ts — дословная копия, импорт типов из среза контракта библиотеки.\nimport type { Issue, IssueComment, IssuePriority, IssueStatusCategory } from '../contract/contract.types.ts';\nimport { gitlabPulls } from './gitlab-pull.lib.ts';\nimport { baseUrl, requestJson } from './http.lib.ts';\nimport { GITLAB_IN_PROGRESS_LABEL, GITLAB_PRIORITY_LABELS } from './mapping.const.ts';\nimport { COMMENT_FILTERS, ISSUE_FILTERS } from './tracker.const.ts';\nimport type { IssueSortField } from './tracker.const.ts';\nimport { TrackerError, assertCommentQuery, assertListQuery, inTimeRange, isRecord, isoTime, lookup, priorityName, requireTarget, stringList, text, toTimestamp } from './tracker.lib.ts';\nimport type { AdapterContext, IssueCapabilities, IssuePatchInput, TrackerAdapter, TrackerDefinition } from './tracker.types.ts';\n\n// Трекер GitLab (D-350): задачи проекта (`group/project` или числовой id) через REST API v4, токен — PRIVATE-TOKEN.\n// У GitLab статус — opened или closed: «в работе» держится меткой `status::in-progress`, приоритет —\n// меткой `priority::<имя>`; служебные метки читаются в поля единой модели и из `labels` убираются. «Отклонена»\n// у GitLab нет. Исполнитель у GitLab задаётся по id пользователя, поэтому только показывается.\n\nconst DEFAULT_URL = 'https://gitlab.com';\nconst TARGET = /^(\\d{1,15}|[\\w.-]+(\\/[\\w.-]+)+)$/;\nconst IID = /^[1-9]\\d{0,14}$/;\n\n/** Возможности списков GitLab (#14): все фильтры единой модели, статус проверяется по странице; comments не сортируется. */\nconst ISSUE_CAPABILITIES: IssueCapabilities = {\n list: { filters: ISSUE_FILTERS, clientSide: ['status'], sorts: ['created', 'updated', 'priority', 'title'] },\n comments: { filters: COMMENT_FILTERS, clientSide: COMMENT_FILTERS, order: ['asc', 'desc'] },\n};\n\n/** Поле сортировки единой модели → order_by GitLab; comments GitLab не сортирует, до сюда не доходит. */\nconst ORDER_BY: Readonly<Partial<Record<IssueSortField, string>>> = {\n created: 'created_at',\n updated: 'updated_at',\n priority: 'priority',\n title: 'title',\n};\n\nexport function gitlabTracker(): TrackerDefinition {\n return {\n descriptor: {\n tracker: 'gitlab',\n title: 'GitLab',\n fields: [\n { name: 'target', required: true, secret: false },\n { name: 'token', required: true, secret: true },\n { name: 'url', required: false, secret: false },\n ],\n features: { create: true, update: true, comment: true, priority: true, labels: true, assignee: false, statuses: ['open', 'in_progress', 'done'] },\n },\n create: (context) => createGitlabAdapter(context),\n issues: ISSUE_CAPABILITIES,\n pulls: gitlabPulls(),\n };\n}\n\nfunction createGitlabAdapter({ connection, fetch }: AdapterContext): TrackerAdapter {\n const target = requireTarget(connection.target, 'путь проекта GitLab, group/project, или его id');\n if (!TARGET.test(target)) throw new TrackerError('invalid_request', 'target GitLab — group/project или числовой id.');\n const root = `${baseUrl(connection.url, DEFAULT_URL)}/api/v4/projects/${encodeURIComponent(target)}/issues`;\n const headers: Record<string, string> = connection.token === undefined || connection.token === '' ? {} : { 'private-token': connection.token };\n const iid = (key: string): string => {\n if (!IID.test(key)) throw new TrackerError('unknown_issue', `В GitLab нет задачи ${key}.`);\n return key;\n };\n const currentOf = async (key: string): Promise<Issue> => issueOf((await requestJson(`${root}/${iid(key)}`, { fetch, headers, missingIsIssue: true })).body);\n return {\n list: async (query) => {\n assertListQuery('Задачи GitLab', ISSUE_CAPABILITIES.list, query, ISSUE_FILTERS);\n const page = pageOf(query.cursor);\n const params = new URLSearchParams({\n state: stateFilter(query.status),\n per_page: String(query.limit),\n page: String(page),\n order_by: query.sort === undefined ? 'created_at' : (ORDER_BY[query.sort.field] ?? 'created_at'),\n sort: query.sort?.direction ?? 'desc',\n });\n if (query.labels !== undefined && query.labels.length > 0) {\n if (query.labels.some((label) => label.includes(','))) throw new TrackerError('invalid_request', 'Задачи GitLab: метка не должна содержать запятую.');\n params.set('labels', query.labels.join(','));\n }\n if (query.assignee !== undefined) params.set(query.assignee === null ? 'assignee_id' : 'assignee_username', query.assignee === null ? 'None' : query.assignee);\n if (query.author !== undefined) params.set('author_username', query.author);\n if (query.search !== undefined) params.set('search', query.search);\n if (query.createdAfter !== undefined) params.set('created_after', isoTime(query.createdAfter));\n if (query.createdBefore !== undefined) params.set('created_before', isoTime(query.createdBefore));\n if (query.updatedAfter !== undefined) params.set('updated_after', isoTime(query.updatedAfter));\n if (query.updatedBefore !== undefined) params.set('updated_before', isoTime(query.updatedBefore));\n const { body, headers: responseHeaders } = await requestJson(`${root}?${params.toString()}`, { fetch, headers });\n const items = (Array.isArray(body) ? body : []).map(issueOf);\n const next = responseHeaders.get('x-next-page');\n return {\n items: query.status === undefined ? items : items.filter((issue) => query.status?.includes(issue.status.category) === true),\n ...(next === null || next === '' ? {} : { nextCursor: next }),\n };\n },\n get: currentOf,\n create: async (input) => {\n const labels = composeLabels(input.labels ?? [], input.priority, undefined);\n const body = { title: input.title, ...(input.description === undefined ? {} : { description: input.description }), ...(labels.length === 0 ? {} : { labels: labels.join(',') }) };\n return issueOf((await requestJson(root, { fetch, headers, method: 'POST', body })).body);\n },\n update: async (key, patch) => {\n const current = patch.labels === undefined && patch.priority === undefined && patch.status === undefined ? undefined : await currentOf(key);\n return issueOf((await requestJson(`${root}/${iid(key)}`, { fetch, headers, method: 'PUT', body: patchBody(patch, current), missingIsIssue: true })).body);\n },\n comments: async (key, query) => {\n assertCommentQuery('Комментарии GitLab', ISSUE_CAPABILITIES.comments, query);\n const page = pageOf(query.cursor);\n const params = new URLSearchParams({ sort: query.order ?? 'asc', order_by: 'created_at', per_page: String(query.limit), page: String(page) });\n const { body, headers: responseHeaders } = await requestJson(`${root}/${iid(key)}/notes?${params.toString()}`, { fetch, headers, missingIsIssue: true });\n const next = responseHeaders.get('x-next-page');\n // Системные заметки («изменил метку») — не комментарии; updatedAfter сверяется с сырым updated_at заметки.\n const items = (Array.isArray(body) ? body : [])\n .filter((note) => isRecord(note) && note.system !== true && inTimeRange(toTimestamp(note.updated_at), query.updatedAfter, undefined))\n .map(commentOf);\n return { items, ...(next === null || next === '' ? {} : { nextCursor: next }) };\n },\n comment: async (key, body) => commentOf((await requestJson(`${root}/${iid(key)}/notes`, { fetch, headers, method: 'POST', body: { body }, missingIsIssue: true })).body),\n };\n}\n\nfunction pageOf(cursor: string | undefined): number {\n const page = cursor === undefined ? 1 : Number(cursor);\n return Number.isInteger(page) && page >= 1 ? page : 1;\n}\n\nfunction stateFilter(status: readonly IssueStatusCategory[] | undefined): string {\n if (status === undefined) return 'all';\n if (status.every((item) => item === 'open' || item === 'in_progress')) return 'opened';\n if (status.every((item) => item === 'done' || item === 'declined')) return 'closed';\n return 'all';\n}\n\nfunction composeLabels(plain: readonly string[], priority: IssuePriority | undefined, status: IssueStatusCategory | undefined): string[] {\n const priorityLabel = priority === undefined ? undefined : priorityName(GITLAB_PRIORITY_LABELS, priority);\n return [...plain, ...(priorityLabel === undefined ? [] : [priorityLabel]), ...(status === 'in_progress' ? [GITLAB_IN_PROGRESS_LABEL] : [])];\n}\n\nfunction patchBody(patch: IssuePatchInput, current: Issue | undefined): Record<string, unknown> {\n const status = patch.status ?? current?.status.category;\n const touchesLabels = patch.labels !== undefined || patch.priority !== undefined || patch.status !== undefined;\n if (patch.status === 'declined') throw new TrackerError('invalid_request', 'В GitLab нет статуса «отклонена».');\n return {\n ...(patch.title === undefined ? {} : { title: patch.title }),\n ...(patch.description === undefined ? {} : { description: patch.description }),\n ...(patch.status === undefined ? {} : { state_event: patch.status === 'done' ? 'close' : 'reopen' }),\n ...(touchesLabels ? { labels: composeLabels(patch.labels ?? current?.labels ?? [], patch.priority ?? current?.priority, status).join(',') } : {}),\n };\n}\n\nfunction issueOf(raw: unknown): Issue {\n const item = isRecord(raw) ? raw : {};\n const names = stringList(item.labels);\n const closed = item.state === 'closed';\n const category: IssueStatusCategory = closed ? 'done' : names.includes(GITLAB_IN_PROGRESS_LABEL) ? 'in_progress' : 'open';\n const priority = names.map((name) => lookup<IssuePriority | undefined>(GITLAB_PRIORITY_LABELS, name, undefined)).find((value) => value !== undefined);\n const description = text(item.description);\n const assignees = Array.isArray(item.assignees) ? item.assignees : [];\n const first = assignees[0];\n const assignee = isRecord(first) ? text(first.username) : undefined;\n const url = text(item.web_url);\n const createdAt = toTimestamp(item.created_at);\n const updatedAt = toTimestamp(item.updated_at);\n const key = typeof item.iid === 'number' ? String(item.iid) : '?';\n return {\n key,\n title: text(item.title) ?? key,\n ...(description === undefined ? {} : { description }),\n status: { category, name: closed ? 'closed' : category === 'in_progress' ? 'in progress' : 'opened' },\n ...(priority === undefined ? {} : { priority }),\n labels: names.filter((name) => name !== GITLAB_IN_PROGRESS_LABEL && !Object.hasOwn(GITLAB_PRIORITY_LABELS, name)),\n ...(assignee === undefined ? {} : { assignee }),\n links: url === undefined ? [] : [{ url, title: 'GitLab' }],\n ...(createdAt === undefined ? {} : { createdAt }),\n ...(updatedAt === undefined ? {} : { updatedAt }),\n };\n}\n\nfunction commentOf(raw: unknown): IssueComment {\n const item = isRecord(raw) ? raw : {};\n const author = isRecord(item.author) ? text(item.author.username) : undefined;\n const createdAt = toTimestamp(item.created_at);\n return { id: typeof item.id === 'number' ? String(item.id) : '?', ...(author === undefined ? {} : { author }), body: typeof item.body === 'string' ? item.body : '', ...(createdAt === undefined ? {} : { createdAt }) };\n}\n","// Адаптер Jira библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/jira.lib.ts — дословная копия, импорт типов из среза контракта библиотеки;\n// фильтры и сортировка списков — свои (#14).\nimport type { Issue, IssueComment, IssuePriority, IssueStatusCategory } from '../contract/contract.types.ts';\nimport { baseUrl, requestJson } from './http.lib.ts';\nimport { JIRA_ISSUE_TYPE, JIRA_PRIORITIES, JIRA_PRIORITY_NAMES, JIRA_STATUS_CATEGORIES } from './mapping.const.ts';\nimport { COMMENT_FILTERS, ISSUE_FILTERS } from './tracker.const.ts';\nimport type { IssueSortField } from './tracker.const.ts';\nimport { TrackerError, assertCommentQuery, assertListQuery, inTimeRange, isRecord, lookup, quoted, requireTarget, stringList, text, toTimestamp } from './tracker.lib.ts';\nimport type { AdapterContext, IssueCapabilities, IssuePatchInput, IssueQuery, TrackerAdapter, TrackerDefinition } from './tracker.types.ts';\n\n// Трекер Jira (D-350): проект по ключу, REST API v2 (описание — обычный текст). Есть `user` — Basic (email и\n// API-токен Cloud), нет — Bearer (персональный токен Server и Data Center). Список — `/search/jql` Cloud, на\n// 404 — классический `/search` Server с курсором `s:<startAt>`. Статус — по `statusCategory`, меняется\n// переходом (transition) в нужную категорию; «отклонена» у Jira нет. Исполнитель у Cloud — accountId, поэтому\n// только показывается.\n\nconst PROJECT_KEY = /^[A-Z][A-Z0-9_]{0,49}$/;\nconst ISSUE_KEY = /^[A-Z][A-Z0-9_]{0,49}-[1-9]\\d{0,14}$/;\nconst FIELDS = 'summary,description,status,priority,labels,assignee,created,updated';\nconst CATEGORY_JQL: Readonly<Partial<Record<IssueStatusCategory, string>>> = { open: '\"To Do\"', in_progress: '\"In Progress\"', done: 'Done' };\n\n/** Возможности списков задач Jira (#14): все фильтры — в JQL на стороне Jira, порядок комментариев asc и desc. */\nconst ISSUE_CAPABILITIES: IssueCapabilities = {\n list: { filters: ISSUE_FILTERS, clientSide: [], sorts: ['created', 'updated', 'priority', 'title'] },\n comments: { filters: COMMENT_FILTERS, clientSide: COMMENT_FILTERS, order: ['asc', 'desc'] },\n};\n\n/** Поле сортировки единой модели → поле ORDER BY JQL; без сортировки — created DESC, как раньше. */\nconst JIRA_SORT_FIELDS: Readonly<Record<Exclude<IssueSortField, 'comments'>, string>> = { created: 'created', updated: 'updated', priority: 'priority', title: 'summary' };\n\nexport function jiraTracker(): TrackerDefinition {\n return {\n descriptor: {\n tracker: 'jira',\n title: 'Jira',\n fields: [\n { name: 'url', required: true, secret: false },\n { name: 'target', required: true, secret: false },\n { name: 'user', required: false, secret: false },\n { name: 'token', required: true, secret: true },\n ],\n features: { create: true, update: true, comment: true, priority: true, labels: true, assignee: false, statuses: ['open', 'in_progress', 'done'] },\n },\n create: (context) => createJiraAdapter(context),\n issues: ISSUE_CAPABILITIES,\n };\n}\n\nfunction createJiraAdapter({ connection, fetch }: AdapterContext): TrackerAdapter {\n if (connection.url === undefined) throw new TrackerError('invalid_request', 'Не задан адрес Jira.');\n const project = requireTarget(connection.target, 'ключ проекта Jira, например PROJ');\n if (!PROJECT_KEY.test(project)) throw new TrackerError('invalid_request', 'target Jira — ключ проекта: заглавные буквы и цифры.');\n const site = baseUrl(connection.url, connection.url);\n const api = `${site}/rest/api/2`;\n const token = connection.token ?? '';\n const headers = { authorization: connection.user === undefined ? `Bearer ${token}` : `Basic ${Buffer.from(`${connection.user}:${token}`).toString('base64')}` };\n const key = (value: string): string => {\n if (!ISSUE_KEY.test(value)) throw new TrackerError('unknown_issue', `В Jira нет задачи ${value}.`);\n return value;\n };\n const toIssue = (raw: unknown): Issue => issueOf(raw, site);\n const load = async (value: string): Promise<Issue> => toIssue((await requestJson(`${api}/issue/${key(value)}?fields=${FIELDS}`, { fetch, headers, missingIsIssue: true })).body);\n return {\n list: async (query) => {\n assertListQuery('Задачи Jira', ISSUE_CAPABILITIES.list, query, ISSUE_FILTERS);\n const jql = listJql(project, query);\n if (jql === undefined) return { items: [] };\n if (query.cursor?.startsWith('s:') !== true) {\n const params = new URLSearchParams({ jql, fields: FIELDS, maxResults: String(query.limit) });\n if (query.cursor !== undefined) params.set('nextPageToken', query.cursor);\n try {\n const { body } = await requestJson(`${api}/search/jql?${params.toString()}`, { fetch, headers });\n const record = isRecord(body) ? body : {};\n const next = text(record.nextPageToken);\n return { items: (Array.isArray(record.issues) ? record.issues : []).map(toIssue), ...(next === undefined || record.isLast === true ? {} : { nextCursor: next }) };\n } catch (error) {\n if (!(error instanceof TrackerError) || !error.message.includes(' 404')) throw error;\n }\n }\n const startAt = query.cursor?.startsWith('s:') === true ? Number(query.cursor.slice(2)) : 0;\n const params = new URLSearchParams({ jql, fields: FIELDS, maxResults: String(query.limit), startAt: String(Number.isInteger(startAt) && startAt >= 0 ? startAt : 0) });\n const { body } = await requestJson(`${api}/search?${params.toString()}`, { fetch, headers });\n const record = isRecord(body) ? body : {};\n const issues = Array.isArray(record.issues) ? record.issues : [];\n const total = typeof record.total === 'number' ? record.total : 0;\n const at = typeof record.startAt === 'number' ? record.startAt : 0;\n return { items: issues.map(toIssue), ...(at + issues.length < total && issues.length > 0 ? { nextCursor: `s:${String(at + issues.length)}` } : {}) };\n },\n get: load,\n create: async (input) => {\n const fields = {\n project: { key: project },\n summary: input.title,\n issuetype: { name: JIRA_ISSUE_TYPE },\n ...(input.description === undefined ? {} : { description: input.description }),\n ...(input.priority === undefined ? {} : { priority: { name: JIRA_PRIORITY_NAMES[input.priority] } }),\n ...(input.labels === undefined ? {} : { labels: input.labels.map((label) => label.replace(/\\s+/g, '-')) }),\n };\n const { body } = await requestJson(`${api}/issue`, { fetch, headers, method: 'POST', body: { fields } });\n const created = isRecord(body) ? text(body.key) : undefined;\n if (created === undefined) throw new TrackerError('failed', 'Jira создала задачу, но не вернула её ключ.');\n return load(created);\n },\n update: async (value, patch) => {\n const fields = fieldsOf(patch);\n if (Object.keys(fields).length > 0) await requestJson(`${api}/issue/${key(value)}`, { fetch, headers, method: 'PUT', body: { fields }, missingIsIssue: true });\n if (patch.status !== undefined) await transition(api, key(value), patch.status, fetch, headers);\n return load(value);\n },\n comments: async (value, query) => {\n assertCommentQuery('Комментарии Jira', ISSUE_CAPABILITIES.comments, query);\n const startAt = query.cursor === undefined ? 0 : Number(query.cursor);\n const params = new URLSearchParams({ startAt: String(Number.isInteger(startAt) && startAt >= 0 ? startAt : 0), maxResults: String(query.limit), orderBy: query.order === 'desc' ? '-created' : 'created' });\n const { body } = await requestJson(`${api}/issue/${key(value)}/comment?${params.toString()}`, { fetch, headers, missingIsIssue: true });\n const record = isRecord(body) ? body : {};\n const raw = Array.isArray(record.comments) ? record.comments : [];\n // Курсор считается по сырой странице: после дофильтровки updatedAfter остаток бывает пуст, а листание продолжается (§3.2 R5).\n const items = raw.filter((item) => inTimeRange(toTimestamp(isRecord(item) ? item.updated : undefined), query.updatedAfter, undefined));\n const total = typeof record.total === 'number' ? record.total : 0;\n const at = typeof record.startAt === 'number' ? record.startAt : 0;\n return { items: items.map(commentOf), ...(at + raw.length < total && raw.length > 0 ? { nextCursor: String(at + raw.length) } : {}) };\n },\n comment: async (value, body) => commentOf((await requestJson(`${api}/issue/${key(value)}/comment`, { fetch, headers, method: 'POST', body: { body }, missingIsIssue: true })).body),\n };\n}\n\n/** JQL списка (#14): project и дальше каждый фильтр через AND; undefined — статусов нет или Jira запрошенные\n * категории не знает (результат пуст, запроса нет, как раньше). */\nfunction listJql(project: string, query: IssueQuery): string | undefined {\n const clauses: string[] = [];\n if (query.status !== undefined) {\n const names = query.status.flatMap((item) => CATEGORY_JQL[item] ?? []);\n if (names.length === 0) return undefined;\n clauses.push(`statusCategory in (${names.join(', ')})`);\n }\n for (const label of query.labels ?? []) clauses.push(`labels = ${quoted(label.replace(/\\s+/g, '-'))}`);\n if (query.assignee !== undefined) clauses.push(query.assignee === null ? 'assignee is EMPTY' : `assignee = ${quoted(query.assignee)}`);\n if (query.author !== undefined) clauses.push(`reporter = ${quoted(query.author)}`);\n if (query.search !== undefined) clauses.push(`text ~ ${quoted(query.search)}`);\n if (query.createdAfter !== undefined) clauses.push(`created >= ${quoted(jiraTime(query.createdAfter, 'down'))}`);\n if (query.createdBefore !== undefined) clauses.push(`created <= ${quoted(jiraTime(query.createdBefore, 'up'))}`);\n if (query.updatedAfter !== undefined) clauses.push(`updated >= ${quoted(jiraTime(query.updatedAfter, 'down'))}`);\n if (query.updatedBefore !== undefined) clauses.push(`updated <= ${quoted(jiraTime(query.updatedBefore, 'up'))}`);\n const sort = query.sort;\n // 'comments' сюда не доходит: assertListQuery отказал раньше — в sorts Jira его нет.\n const field = (sort === undefined ? 'created' : sort.field) as Exclude<IssueSortField, 'comments'>;\n const direction = sort?.direction ?? 'desc';\n return `${[`project = ${quoted(project)}`, ...clauses].join(' AND ')} ORDER BY ${JIRA_SORT_FIELDS[field]} ${direction.toUpperCase()}`;\n}\n\n/** Время JQL: UTC, «yyyy/MM/dd HH:mm»; нижняя граница вниз к минуте, верхняя — вверх, чтобы границы были включительны (#14, R2). */\nfunction jiraTime(ms: number, outward: 'down' | 'up'): string {\n const at = new Date(outward === 'down' ? Math.floor(ms / 60000) * 60000 : Math.ceil(ms / 60000) * 60000);\n const pad = (value: number): string => String(value).padStart(2, '0');\n return `${String(at.getUTCFullYear())}/${pad(at.getUTCMonth() + 1)}/${pad(at.getUTCDate())} ${pad(at.getUTCHours())}:${pad(at.getUTCMinutes())}`;\n}\n\nfunction fieldsOf(patch: IssuePatchInput): Record<string, unknown> {\n return {\n ...(patch.title === undefined ? {} : { summary: patch.title }),\n ...(patch.description === undefined ? {} : { description: patch.description }),\n ...(patch.priority === undefined ? {} : { priority: { name: JIRA_PRIORITY_NAMES[patch.priority] } }),\n ...(patch.labels === undefined ? {} : { labels: patch.labels.map((label) => label.replace(/\\s+/g, '-')) }),\n };\n}\n\n/** Переводит задачу в категорию: берёт первый доступный переход, чей статус назначения лежит в ней. */\nasync function transition(api: string, key: string, category: IssueStatusCategory, fetch: AdapterContext['fetch'], headers: Record<string, string>): Promise<void> {\n const { body } = await requestJson(`${api}/issue/${key}/transitions`, { fetch, headers, missingIsIssue: true });\n const list = isRecord(body) && Array.isArray(body.transitions) ? body.transitions : [];\n const match = list.find((item) => {\n if (!isRecord(item) || !isRecord(item.to) || !isRecord(item.to.statusCategory)) return false;\n return lookup<IssueStatusCategory | undefined>(JIRA_STATUS_CATEGORIES, item.to.statusCategory.key, undefined) === category;\n });\n const id = isRecord(match) ? text(match.id) : undefined;\n if (id === undefined) throw new TrackerError('invalid_request', `Из текущего статуса Jira нет перехода в категорию ${category}.`);\n await requestJson(`${api}/issue/${key}/transitions`, { fetch, headers, method: 'POST', body: { transition: { id } }, missingIsIssue: true });\n}\n\nfunction issueOf(raw: unknown, site: string): Issue {\n const item = isRecord(raw) ? raw : {};\n const fields = isRecord(item.fields) ? item.fields : {};\n const status = isRecord(fields.status) ? fields.status : {};\n const category = isRecord(status.statusCategory) ? status.statusCategory.key : undefined;\n const priorityName = isRecord(fields.priority) && typeof fields.priority.name === 'string' ? fields.priority.name.toLowerCase() : undefined;\n const priority = lookup<IssuePriority | undefined>(JIRA_PRIORITIES, priorityName, undefined);\n const assignee = isRecord(fields.assignee) ? (text(fields.assignee.displayName) ?? text(fields.assignee.name)) : undefined;\n const description = text(fields.description);\n const createdAt = toTimestamp(fields.created);\n const updatedAt = toTimestamp(fields.updated);\n const key = text(item.key) ?? '?';\n return {\n key,\n title: text(fields.summary) ?? key,\n ...(description === undefined ? {} : { description }),\n status: { category: lookup(JIRA_STATUS_CATEGORIES, category, 'open'), name: text(status.name) ?? 'To Do' },\n ...(priority === undefined ? {} : { priority }),\n labels: stringList(fields.labels),\n ...(assignee === undefined ? {} : { assignee }),\n links: [{ url: `${site}/browse/${key}`, title: 'Jira' }],\n ...(createdAt === undefined ? {} : { createdAt }),\n ...(updatedAt === undefined ? {} : { updatedAt }),\n };\n}\n\nfunction commentOf(raw: unknown): IssueComment {\n const item = isRecord(raw) ? raw : {};\n const author = isRecord(item.author) ? text(item.author.displayName) : undefined;\n const createdAt = toTimestamp(item.created);\n return { id: text(item.id) ?? '?', ...(author === undefined ? {} : { author }), body: typeof item.body === 'string' ? item.body : '', ...(createdAt === undefined ? {} : { createdAt }) };\n}\n","// Локальный трекер библиотеки @smwb/onreel-git-mcp (часть E выделения, D-003).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/local.lib.ts — CRUD через функции ledger заменён на порт LocalIssueStore ядра\n// (kernel/store.types.ts): хранилище пишет потребитель (в onreel — поверх ledger), эталонная\n// реализация в памяти — в тестах библиотеки (test/helpers/tracker-fixtures.lib.ts).\n// Фильтры единой модели (#14): хранилище умеет только статус и keyset-страницы, остальные фильтры\n// адаптер проверяет по полученной странице — порт LocalIssueStore не меняется (D-003).\nimport type { Issue } from '../contract/contract.types.ts';\nimport type { LocalCommentRow, LocalIssueRow } from '../kernel/store.types.ts';\nimport { ALL_STATUSES } from './mapping.const.ts';\nimport { COMMENT_FILTERS, ISSUE_FILTERS } from './tracker.const.ts';\nimport { TrackerError, assertCommentQuery, assertListQuery, containsText, inTimeRange } from './tracker.lib.ts';\nimport type { AdapterContext, IssueCapabilities, IssueQuery, TrackerAdapter, TrackerDefinition } from './tracker.types.ts';\n\n// Локальный трекер (D-350): задачи в хранилище потребителя, без внешних сервисов. Номер задачи — её ключ.\n\nconst STATUS_NAMES = { open: 'Open', in_progress: 'In progress', done: 'Done', declined: 'Declined' } as const;\n\n/** Возможности списков локального трекера (#14, §3.6): из фильтров запроса хранилище знает только\n * статус, остальное проверяется по странице (D-004). Автора у локальной задачи нет и сортировки нет:\n * store отдаёт порядок ledger — новые первыми. */\nconst ISSUE_CAPABILITIES: IssueCapabilities = {\n list: {\n filters: ['status', 'labels', 'assignee', 'search', 'createdAfter', 'createdBefore', 'updatedAfter', 'updatedBefore'],\n clientSide: ['labels', 'assignee', 'search', 'createdAfter', 'createdBefore', 'updatedAfter', 'updatedBefore'],\n sorts: [],\n },\n comments: { filters: COMMENT_FILTERS, clientSide: COMMENT_FILTERS, order: ['asc'] },\n};\n\nexport function localTracker(): TrackerDefinition {\n return {\n descriptor: {\n tracker: 'local',\n title: 'Local',\n fields: [],\n features: { create: true, update: true, comment: true, priority: true, labels: true, assignee: true, statuses: [...ALL_STATUSES] },\n },\n issues: ISSUE_CAPABILITIES,\n create: (context) => createLocalAdapter(context),\n };\n}\n\nfunction createLocalAdapter({ store, projectId, author }: AdapterContext): TrackerAdapter {\n const number = (key: string): number => {\n if (!/^[1-9]\\d{0,14}$/.test(key)) throw new TrackerError('unknown_issue', `В локальном трекере нет задачи ${key}.`);\n return Number(key);\n };\n const mustGet = (key: string): LocalIssueRow => {\n const row = store.getLocalIssue(projectId, number(key));\n if (row === undefined) throw new TrackerError('unknown_issue', `В локальном трекере нет задачи ${key}.`);\n return row;\n };\n return {\n // list и comments async: отказ проверки запроса — rejected promise, как у остальных адаптеров.\n list: async (query) => {\n assertListQuery('Задачи Local', ISSUE_CAPABILITIES.list, query, ISSUE_FILTERS);\n const page = store.listLocalIssues(projectId, { limit: query.limit, ...(query.cursor === undefined ? {} : { cursor: query.cursor }), ...(query.status === undefined ? {} : { status: query.status }) });\n return { items: page.items.filter((row) => matchesIssueQuery(row, query)).map(toIssue), ...(page.nextCursor === undefined ? {} : { nextCursor: page.nextCursor }) };\n },\n get: (key) => Promise.resolve(toIssue(mustGet(key))),\n create: (input) => Promise.resolve(toIssue(store.createLocalIssue(projectId, input))),\n update: (key, patch) => {\n const row = store.updateLocalIssue(projectId, mustGet(key).number, patch);\n if (row === undefined) throw new TrackerError('unknown_issue', `В локальном трекере нет задачи ${key}.`);\n return Promise.resolve(toIssue(row));\n },\n comments: async (key, query) => {\n assertCommentQuery('Комментарии Local', ISSUE_CAPABILITIES.comments, query);\n const page = store.listLocalComments(projectId, mustGet(key).number, { limit: query.limit, ...(query.cursor === undefined ? {} : { cursor: query.cursor }) });\n // Локальные комментарии не правятся, поэтому updatedAfter сверяется с createdAt; порядок — только asc (§3.7 A6).\n const items = query.updatedAfter === undefined ? page.items : page.items.filter((row) => inTimeRange(row.createdAt, query.updatedAfter, undefined));\n return { items: items.map(toComment), ...(page.nextCursor === undefined ? {} : { nextCursor: page.nextCursor }) };\n },\n comment: (key, body) => Promise.resolve(toComment(store.addLocalComment(projectId, mustGet(key).number, body, author))),\n };\n}\n\n/** Фильтры единой модели, которые локальный трекер проверяет по странице (D-004): метки — все сразу (И),\n * assignee null — задачи без исполнителя, search — подстрока заголовка или описания без учёта регистра,\n * время — включительно с обеих сторон (R2, R3). */\nfunction matchesIssueQuery(row: LocalIssueRow, query: IssueQuery): boolean {\n if (query.labels !== undefined && !query.labels.every((label) => row.labels.includes(label))) return false;\n const assignee = query.assignee;\n if (assignee !== undefined && (assignee === null ? row.assignee !== undefined : row.assignee !== assignee)) return false;\n if (query.search !== undefined && !containsText([row.title, row.description], query.search)) return false;\n return inTimeRange(row.createdAt, query.createdAfter, query.createdBefore) && inTimeRange(row.updatedAt, query.updatedAfter, query.updatedBefore);\n}\n\nfunction toIssue(row: LocalIssueRow): Issue {\n return {\n key: String(row.number),\n title: row.title,\n ...(row.description === undefined ? {} : { description: row.description }),\n status: { category: row.status, name: STATUS_NAMES[row.status] },\n ...(row.priority === undefined ? {} : { priority: row.priority }),\n labels: row.labels,\n ...(row.assignee === undefined ? {} : { assignee: row.assignee }),\n links: [],\n createdAt: row.createdAt,\n updatedAt: row.updatedAt,\n };\n}\n\nfunction toComment(row: LocalCommentRow): { id: string; author?: string; body: string; createdAt: number } {\n return { id: String(row.id), ...(row.author === undefined ? {} : { author: row.author }), body: row.body, createdAt: row.createdAt };\n}\n","// Адаптер pull request-ов SourceCraft библиотеки @smwb/onreel-git-mcp — свой (#15).\n// Раздел pulls (D-005) на том же подключении, что и задачи: QL filter списка, отдельные\n// конечные точки состояний, асинхронное слияние (202 → get; failed/cancel — conflict).\nimport type { IssueComment } from '../contract/contract.types.ts';\nimport { baseUrl, requestJson } from './http.lib.ts';\nimport { redactSecretText } from '../kernel/redact.lib.ts';\nimport { SOURCECRAFT_PULL_STATUSES } from './mapping.const.ts';\nimport type { PullRequest, PullRequestSortField, PullRequestStatusCategory } from './pull.schema.ts';\nimport { pullRequestFilterSchema, pullRequestStatusCategorySchema } from './pull.schema.ts';\nimport type { MergeInput, NewPullRequestInput, PullRequestAdapter, PullRequestCapabilities, PullRequestDefinition, PullRequestQuery } from './pull.types.ts';\nimport { COMMENT_FILTERS } from './tracker.const.ts';\nimport { TrackerError, assertCommentQuery, assertListQuery, containsText, inTimeRange, isRecord, keysFor, lookup, quoted, requireTarget, stringList, text, toTimestamp } from './tracker.lib.ts';\nimport type { AdapterContext, CommentQuery } from './tracker.types.ts';\n\nconst DEFAULT_API = 'https://api.sourcecraft.tech';\nconst TARGET = /^[\\w.-]+\\/[\\w.-]+$/;\nconst SLUG = /^[\\w-]{1,100}$/;\nconst SHA = /^[0-9a-f]{7,64}$/;\n\n/** Поля сортировки единой модели → поля sort_by SourceCraft. */\nconst PULL_SORT_FIELDS_UPSTREAM: Readonly<Record<PullRequestSortField, string>> = {\n created: 'created_at',\n updated: 'updated_at',\n title: 'title',\n};\n\n/** Возможности PR SourceCraft (§3.6): QL фильтрует статус, автора и ветки сервером; метки, поиск и время — по странице. */\nconst PULL_CAPABILITIES: PullRequestCapabilities = {\n list: {\n filters: pullRequestFilterSchema.options,\n clientSide: ['labels', 'search', 'createdAfter', 'createdBefore', 'updatedAfter', 'updatedBefore'],\n sorts: ['created', 'updated', 'title'],\n },\n comments: { filters: COMMENT_FILTERS, clientSide: COMMENT_FILTERS, order: ['asc', 'desc'] },\n create: true,\n createDraft: true,\n update: ['title', 'description', 'target'],\n statuses: ['draft', 'open', 'closed'],\n comment: true,\n merge: ['merge', 'squash', 'rebase'],\n deleteSourceOnMerge: true,\n};\n\nexport function sourcecraftPulls(): PullRequestDefinition {\n return { capabilities: PULL_CAPABILITIES, create: (context) => createPullAdapter(context) };\n}\n\nfunction createPullAdapter({ connection, fetch }: AdapterContext): PullRequestAdapter {\n const target = requireTarget(connection.target, 'org/repo репозитория SourceCraft');\n if (!TARGET.test(target)) throw new TrackerError('invalid_request', 'target SourceCraft — org/repo.');\n const api = baseUrl(connection.url, DEFAULT_API);\n const root = `${api}/repos/${target}/pulls`;\n const headers = { authorization: `Bearer ${connection.token ?? ''}` };\n const missing = (key: string): { failure: 'not_found'; message: string } => ({ failure: 'not_found', message: `В SourceCraft нет PR ${key}.` });\n const slug = (key: string): string => {\n if (!SLUG.test(key)) throw new TrackerError('not_found', `В SourceCraft нет PR ${key}.`);\n return key;\n };\n const getPull = async (key: string): Promise<PullRequest> =>\n pullOf((await requestJson(`${root}/${slug(key)}`, { fetch, headers, missing: missing(key) })).body);\n return {\n list: async (query) => {\n assertListQuery('PR SourceCraft', PULL_CAPABILITIES.list, query, pullRequestFilterSchema.options);\n const status = usedStatuses(query.status);\n const params = new URLSearchParams({ page_size: String(query.limit) });\n if (query.cursor !== undefined) params.set('page_token', query.cursor);\n const filter = pullFilterOf(query, status);\n if (filter !== undefined) params.set('filter', filter);\n if (query.sort !== undefined) params.set('sort_by', `${query.sort.direction === 'asc' ? '' : '-'}${PULL_SORT_FIELDS_UPSTREAM[query.sort.field]}`);\n const { body } = await requestJson(`${root}?${params.toString()}`, { fetch, headers });\n const record = isRecord(body) ? body : {};\n const pulls = (Array.isArray(record.pull_requests) ? record.pull_requests : []).map(pullOf).filter((pull) => matchesPage(pull, query));\n return { items: pulls, ...nextOf(record.next_page_token) };\n },\n get: (key) => getPull(key),\n create: async (input) => pullOf((await requestJson(root, { fetch, headers, method: 'POST', body: createBody(input) })).body),\n update: async (key, patch) => {\n const id = slug(key);\n let updated: unknown;\n if (patch.title !== undefined || patch.description !== undefined || patch.target !== undefined) {\n const body = {\n ...(patch.title === undefined ? {} : { title: patch.title }),\n ...(patch.description === undefined ? {} : { description: patch.description }),\n ...(patch.target === undefined ? {} : { target_branch: patch.target }),\n };\n updated = (await requestJson(`${root}/${id}`, { fetch, headers, method: 'PATCH', body, missing: missing(key) })).body;\n }\n if (patch.status !== undefined) {\n const action = statusActionOf(patch.status, (await getPull(key)).status.category);\n if (action !== undefined) await requestJson(`${root}/${id}/${action}`, { fetch, headers, method: 'POST', missing: missing(key) });\n return getPull(key);\n }\n return pullOf(updated ?? (await requestJson(`${root}/${id}`, { fetch, headers, missing: missing(key) })).body);\n },\n merge: async (key, input: MergeInput) => {\n const id = slug(key);\n if (input.message !== undefined) throw new TrackerError('unsupported', 'PR SourceCraft: сообщение коммита слияния не поддерживается.');\n if (input.method !== undefined && !PULL_CAPABILITIES.merge.includes(input.method)) {\n throw new TrackerError('unsupported', `PR SourceCraft: слияние способом ${input.method} не поддерживается.`);\n }\n if (input.headSha !== undefined) {\n const current = await getPull(key);\n // Проверка на клиенте, а не атомарная: push между чтением и POST /merge не отсекается; сравниваем в нижнем регистре.\n if ((current.headSha ?? '').toLowerCase() !== input.headSha.toLowerCase()) {\n throw new TrackerError('conflict', `Голова PR ${key} изменилась: ожидался ${input.headSha}, сейчас ${current.headSha ?? 'неизвестен'}.`);\n }\n }\n const { body } = await requestJson(`${root}/${id}/merge`, {\n fetch,\n headers,\n method: 'POST',\n // squash/rebase по умолчанию наследуются из настройки репозитория — без method не шлём явно false.\n body: {\n ...(input.method === undefined ? {} : { squash: input.method === 'squash', rebase: input.method === 'rebase' }),\n ...(input.deleteSource === undefined ? {} : { delete_branch: input.deleteSource }),\n },\n missing: missing(key),\n });\n const operation = isRecord(body) ? body : {};\n if (operation.status === 'failed' || operation.status === 'cancel') {\n const errorMessage = isRecord(operation.error) ? text(operation.error.message) : undefined;\n throw new TrackerError('conflict', `Слияние PR ${key} не запущено: ${redactSecretText(errorMessage ?? String(operation.status))}.`);\n }\n return getPull(key);\n },\n comments: async (key, query: CommentQuery) => {\n const id = slug(key);\n assertCommentQuery('Комментарии PR SourceCraft', PULL_CAPABILITIES.comments, query);\n const params = new URLSearchParams({ page_size: String(query.limit) });\n if (query.cursor !== undefined) params.set('page_token', query.cursor);\n if (query.order !== undefined) params.set('sort_by', query.order === 'asc' ? 'created_at' : '-created_at');\n const { body } = await requestJson(`${root}/${id}/comments?${params.toString()}`, { fetch, headers, missing: missing(key) });\n const record = isRecord(body) ? body : {};\n const rawComments = Array.isArray(record.pull_request_comments) ? record.pull_request_comments : [];\n const visible = rawComments.filter((raw) => !(isRecord(raw) && raw.is_deleted === true));\n const filtered = query.updatedAfter === undefined ? visible : visible.filter((raw) => inTimeRange(toTimestamp(isRecord(raw) ? raw.updated_at : undefined), query.updatedAfter, undefined));\n return { items: filtered.map(commentOf), ...nextOf(record.next_page_token) };\n },\n comment: async (key, body) => commentOf((await requestJson(`${root}/${slug(key)}/comments`, { fetch, headers, method: 'POST', body: { body }, missing: missing(key) })).body),\n };\n}\n\n/** Тело создания PR: publish по умолчанию false у трекера — открытый PR шлём явно. */\nfunction createBody(input: NewPullRequestInput): Record<string, unknown> {\n return {\n title: input.title,\n source_branch: input.source,\n target_branch: input.target,\n ...(input.description === undefined ? {} : { description: input.description }),\n publish: input.draft !== true,\n };\n}\n\n/** Конечная точка перехода состояния из текущего; переход «в то же состояние» — без запроса. */\nfunction statusActionOf(requested: Exclude<PullRequestStatusCategory, 'merged'>, current: PullRequestStatusCategory): string | undefined {\n if (current === requested) return undefined;\n if (requested === 'draft') return 'draft';\n if (requested === 'open') return current === 'draft' ? 'publish' : 'reopen';\n return 'discard';\n}\n\n/** Статусы списка: пустой массив — без фильтра; неизвестная категория — invalid_request до запроса. */\nfunction usedStatuses(status: readonly PullRequestStatusCategory[] | undefined): readonly PullRequestStatusCategory[] | undefined {\n if (status === undefined || status.length === 0) return undefined;\n for (const item of status) {\n if (!pullRequestStatusCategorySchema.options.includes(item)) {\n throw new TrackerError('invalid_request', `PR SourceCraft: неизвестная категория статуса ${String(item)}.`);\n }\n }\n return status;\n}\n\n/** Фильтры, которые QL SourceCraft не умеет, — по полученной странице (D-004). */\nfunction matchesPage(pull: PullRequest, query: PullRequestQuery): boolean {\n if (query.labels !== undefined && !query.labels.every((label) => pull.labels.includes(label))) return false;\n if (query.search !== undefined && !containsText([pull.title, pull.description], query.search)) return false;\n return inTimeRange(pull.createdAt, query.createdAfter, query.createdBefore) && inTimeRange(pull.updatedAt, query.updatedAfter, query.updatedBefore);\n}\n\n/** QL фильтр списка PR: статус — слаги через обратную таблицу; метки, поиск и время — на странице. */\nfunction pullFilterOf(query: PullRequestQuery, status: readonly PullRequestStatusCategory[] | undefined): string | undefined {\n const clauses: string[] = [];\n if (status !== undefined) {\n const slugs = [...new Set(keysFor(SOURCECRAFT_PULL_STATUSES, status))];\n clauses.push(`status in (${slugs.join(', ')})`);\n }\n if (query.author !== undefined) clauses.push(`author_slug=${quoted(query.author)}`);\n if (query.source !== undefined) clauses.push(`source_branch=${quoted(query.source)}`);\n if (query.target !== undefined) clauses.push(`target_branch=${quoted(query.target)}`);\n return clauses.length === 0 ? undefined : clauses.join(' and ');\n}\n\n/** Токен следующей страницы; пустая строка — последняя страница. */\nfunction nextOf(token: unknown): { nextCursor?: string } {\n const value = text(token);\n return value === undefined ? {} : { nextCursor: value };\n}\n\n/** PR единой модели из ответа трекера; веб-адрес PR не подтверждён (Q9) — ссылки пустые. */\nfunction pullOf(raw: unknown): PullRequest {\n const item = isRecord(raw) ? raw : {};\n const source = isRecord(item.source) ? item.source : {};\n const target = isRecord(item.target) ? item.target : {};\n const headSha = text(source.sha);\n const description = text(item.description);\n const author = isRecord(item.author) ? text(item.author.slug) : undefined;\n const createdAt = toTimestamp(item.created_at);\n const updatedAt = toTimestamp(item.updated_at);\n const mergedAt = toTimestamp(item.merged_at);\n const closedAt = toTimestamp(item.closed_at);\n const key = text(item.slug) ?? '?';\n const statusName = text(item.status) ?? 'open';\n return {\n key,\n title: text(item.title) ?? key,\n ...(description === undefined ? {} : { description }),\n status: { category: lookup(SOURCECRAFT_PULL_STATUSES, statusName, 'open'), name: statusName },\n ...(author === undefined ? {} : { author }),\n source: text(source.ref) ?? text(item.source_branch) ?? '?',\n target: text(target.ref) ?? text(item.target_branch) ?? '?',\n ...(headSha !== undefined && SHA.test(headSha) ? { headSha } : {}),\n labels: Array.isArray(item.labels) ? stringList(item.labels.map((label) => (isRecord(label) ? label.name : undefined))) : [],\n links: [],\n ...(createdAt === undefined ? {} : { createdAt }),\n ...(updatedAt === undefined ? {} : { updatedAt }),\n ...(mergedAt === undefined ? {} : { mergedAt }),\n ...(closedAt === undefined ? {} : { closedAt }),\n };\n}\n\nfunction commentOf(raw: unknown): IssueComment {\n const item = isRecord(raw) ? raw : {};\n const author = isRecord(item.author) ? text(item.author.slug) : undefined;\n const createdAt = toTimestamp(item.created_at);\n return { id: text(item.id) ?? '?', ...(author === undefined ? {} : { author }), body: typeof item.body === 'string' ? item.body : '', ...(createdAt === undefined ? {} : { createdAt }) };\n}\n","// Адаптер SourceCraft библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/sourcecraft.lib.ts — дословная копия, импорт типов из среза контракта библиотеки;\n// фильтры и сортировка списков — свои (#14): QL filter, sort_by, проверка по возможностям.\nimport type { Issue, IssueComment } from '../contract/contract.types.ts';\nimport { baseUrl, requestJson } from './http.lib.ts';\nimport { ALL_STATUSES, SOURCECRAFT_PRIORITIES, SOURCECRAFT_STATUSES, SOURCECRAFT_STATUS_FILTER, SOURCECRAFT_STATUS_SLUGS } from './mapping.const.ts';\nimport { COMMENT_FILTERS, ISSUE_FILTERS } from './tracker.const.ts';\nimport type { IssueSortField } from './tracker.const.ts';\nimport { TrackerError, assertCommentQuery, assertListQuery, inTimeRange, isRecord, isoTime, lookup, quoted, requireTarget, stringList, text, toTimestamp } from './tracker.lib.ts';\nimport type { AdapterContext, IssueCapabilities, IssuePatchInput, IssueQuery, TrackerAdapter, TrackerDefinition } from './tracker.types.ts';\nimport { sourcecraftPulls } from './sourcecraft-pull.lib.ts';\n\n// Трекер SourceCraft (D-350): задачи репозитория `org/repo` через REST API, токен — Bearer. Исполнитель и метки\n// у SourceCraft задаются по id, а не по имени: адаптер их показывает, но не меняет.\n\nconst DEFAULT_API = 'https://api.sourcecraft.tech';\nconst DEFAULT_WEB = 'https://sourcecraft.dev';\nconst TARGET = /^[\\w.-]+\\/[\\w.-]+$/;\nconst SLUG = /^[\\w-]{1,100}$/;\n\n/** Поля сортировки единой модели → поля sort_by SourceCraft; comments адаптер не поддерживает (отказ в assertListQuery). */\nconst ISSUE_SORT_FIELDS_UPSTREAM: Readonly<Partial<Record<IssueSortField, string>>> = {\n created: 'created_at',\n updated: 'updated_at',\n priority: 'priority',\n title: 'title',\n};\n\n/** Возможности списков SourceCraft: QL фильтрует сервером; null исполнителя в списке и updatedAfter\n * комментариев проверяются по полученной странице (D-004). */\nconst ISSUE_CAPABILITIES: IssueCapabilities = {\n list: { filters: ISSUE_FILTERS, clientSide: ['assignee'], sorts: ['created', 'updated', 'priority', 'title'] },\n comments: { filters: COMMENT_FILTERS, clientSide: COMMENT_FILTERS, order: ['asc', 'desc'] },\n};\n\nexport function sourcecraftTracker(): TrackerDefinition {\n return {\n descriptor: {\n tracker: 'sourcecraft',\n title: 'SourceCraft',\n fields: [\n { name: 'target', required: true, secret: false },\n { name: 'token', required: true, secret: true },\n { name: 'url', required: false, secret: false },\n ],\n features: { create: true, update: true, comment: true, priority: true, labels: false, assignee: false, statuses: [...ALL_STATUSES] },\n },\n issues: ISSUE_CAPABILITIES,\n create: (context) => createSourceCraftAdapter(context),\n pulls: sourcecraftPulls(),\n };\n}\n\nfunction createSourceCraftAdapter({ connection, fetch }: AdapterContext): TrackerAdapter {\n const target = requireTarget(connection.target, 'org/repo репозитория SourceCraft');\n if (!TARGET.test(target)) throw new TrackerError('invalid_request', 'target SourceCraft — org/repo.');\n const api = baseUrl(connection.url, DEFAULT_API);\n const root = `${api}/repos/${target}/issues`;\n const headers = { authorization: `Bearer ${connection.token ?? ''}` };\n const web = connection.url === undefined ? `${DEFAULT_WEB}/${target}/issues` : undefined;\n const slug = (key: string): string => {\n if (!SLUG.test(key)) throw new TrackerError('unknown_issue', `В SourceCraft нет задачи ${key}.`);\n return key;\n };\n const toIssue = (raw: unknown): Issue => issueOf(raw, web);\n return {\n list: async (query) => {\n assertListQuery('Задачи SourceCraft', ISSUE_CAPABILITIES.list, query, ISSUE_FILTERS);\n const params = new URLSearchParams({ page_size: String(query.limit) });\n if (query.cursor !== undefined) params.set('page_token', query.cursor);\n const filter = issueFilterOf(query);\n if (filter !== undefined) params.set('filter', filter);\n if (query.sort !== undefined) params.set('sort_by', `${query.sort.direction === 'asc' ? '' : '-'}${issueSortFieldOf(query.sort.field)}`);\n const { body } = await requestJson(`${root}?${params.toString()}`, { fetch, headers });\n const record = isRecord(body) ? body : {};\n let issues = (Array.isArray(record.issues) ? record.issues : []).map(toIssue);\n if (query.status !== undefined) issues = issues.filter((issue) => query.status?.includes(issue.status.category) === true);\n if (query.assignee === null) issues = issues.filter((issue) => issue.assignee === undefined);\n return { items: issues, ...nextOf(record.next_page_token) };\n },\n get: async (key) => toIssue((await requestJson(`${root}/${slug(key)}`, { fetch, headers, missingIsIssue: true })).body),\n create: async (input) => {\n const body = { title: input.title, ...(input.description === undefined ? {} : { description: input.description }), ...(input.priority === undefined ? {} : { priority: input.priority }) };\n return toIssue((await requestJson(root, { fetch, headers, method: 'POST', body })).body);\n },\n update: async (key, patch) => toIssue((await requestJson(`${root}/${slug(key)}`, { fetch, headers, method: 'PATCH', body: patchBody(patch), missingIsIssue: true })).body),\n comments: async (key, query) => {\n assertCommentQuery('Комментарии SourceCraft', ISSUE_CAPABILITIES.comments, query);\n const params = new URLSearchParams({ page_size: String(query.limit) });\n if (query.cursor !== undefined) params.set('page_token', query.cursor);\n if (query.order !== undefined) params.set('sort_by', query.order === 'asc' ? 'created_at' : '-created_at');\n const { body } = await requestJson(`${root}/${slug(key)}/comments?${params.toString()}`, { fetch, headers, missingIsIssue: true });\n const record = isRecord(body) ? body : {};\n const rawComments = Array.isArray(record.issue_comments) ? record.issue_comments : [];\n const filtered = query.updatedAfter === undefined ? rawComments : rawComments.filter((raw) => inTimeRange(toTimestamp(isRecord(raw) ? raw.updated_at : undefined), query.updatedAfter, undefined));\n return { items: filtered.map(commentOf), ...nextOf(record.next_page_token) };\n },\n comment: async (key, body) => commentOf((await requestJson(`${root}/${slug(key)}/comments`, { fetch, headers, method: 'POST', body: { body }, missingIsIssue: true })).body),\n };\n}\n\nfunction patchBody(patch: IssuePatchInput): Record<string, unknown> {\n return {\n ...(patch.title === undefined ? {} : { title: patch.title }),\n ...(patch.description === undefined ? {} : { description: patch.description }),\n ...(patch.status === undefined ? {} : { status_slug: SOURCECRAFT_STATUS_SLUGS[patch.status] }),\n ...(patch.priority === undefined ? {} : { priority: patch.priority }),\n };\n}\n\n/** Токен следующей страницы; пустая строка — последняя страница. */\nfunction nextOf(token: unknown): { nextCursor?: string } {\n const value = text(token);\n return value === undefined ? {} : { nextCursor: value };\n}\n\n/** Поле сортировки единой модели → поле sort_by SourceCraft; неподдерживаемое поле — отказ (R-002). */\nfunction issueSortFieldOf(field: IssueSortField): string {\n const upstream = ISSUE_SORT_FIELDS_UPSTREAM[field];\n if (upstream === undefined) throw new TrackerError('unsupported', `Задачи SourceCraft: сортировка по ${field} не поддерживается.`);\n return upstream;\n}\n\n/** QL фильтр списка задач: предложения через ` and `; исполнитель null — на странице, а не в QL (assignee_id=null даёт 500). */\nfunction issueFilterOf(query: IssueQuery): string | undefined {\n const clauses: string[] = [];\n if (query.status !== undefined && query.status.length > 0) {\n const slugs = [...new Set(query.status.flatMap((category) => SOURCECRAFT_STATUS_FILTER[category]))];\n clauses.push(`status in (${slugs.join(', ')})`);\n }\n for (const label of query.labels ?? []) clauses.push(`label_slug=${quoted(label)}`);\n if (typeof query.assignee === 'string') clauses.push(`assignee_slug=${quoted(query.assignee)}`);\n if (query.author !== undefined) clauses.push(`author_slug=${quoted(query.author)}`);\n if (query.search !== undefined) clauses.push(`title=${quoted(query.search)}`);\n if (query.createdAfter !== undefined) clauses.push(`created_at>=${quoted(isoTime(query.createdAfter))}`);\n if (query.createdBefore !== undefined) clauses.push(`created_at<=${quoted(isoTime(query.createdBefore))}`);\n if (query.updatedAfter !== undefined) clauses.push(`updated_at>=${quoted(isoTime(query.updatedAfter))}`);\n if (query.updatedBefore !== undefined) clauses.push(`updated_at<=${quoted(isoTime(query.updatedBefore))}`);\n return clauses.length === 0 ? undefined : clauses.join(' and ');\n}\n\nfunction issueOf(raw: unknown, web: string | undefined): Issue {\n const item = isRecord(raw) ? raw : {};\n const status = isRecord(item.status) ? item.status : {};\n const slug = text(item.slug) ?? '?';\n const statusSlug = text(status.slug) ?? 'open';\n const priority = lookup<Issue['priority']>(SOURCECRAFT_PRIORITIES, item.priority, undefined);\n const assignee = isRecord(item.assignee) ? text(item.assignee.slug) : undefined;\n const labels = Array.isArray(item.labels) ? stringList(item.labels.map((label) => (isRecord(label) ? label.name : undefined))) : [];\n const description = text(item.description);\n const createdAt = toTimestamp(item.created_at);\n const updatedAt = toTimestamp(item.updated_at);\n return {\n key: slug,\n title: text(item.title) ?? slug,\n ...(description === undefined ? {} : { description }),\n status: { category: lookup(SOURCECRAFT_STATUSES, statusSlug, 'open'), name: text(status.name) ?? statusSlug },\n ...(priority === undefined ? {} : { priority }),\n labels,\n ...(assignee === undefined ? {} : { assignee }),\n links: web === undefined ? [] : [{ url: `${web}/${slug}`, title: 'SourceCraft' }],\n ...(createdAt === undefined ? {} : { createdAt }),\n ...(updatedAt === undefined ? {} : { updatedAt }),\n };\n}\n\nfunction commentOf(raw: unknown): IssueComment {\n const item = isRecord(raw) ? raw : {};\n const author = isRecord(item.author) ? text(item.author.slug) : undefined;\n const createdAt = toTimestamp(item.created_at);\n return { id: text(item.id) ?? '?', ...(author === undefined ? {} : { author }), body: typeof item.body === 'string' ? item.body : '', ...(createdAt === undefined ? {} : { createdAt }) };\n}\n","// Встроенные трекеры библиотеки @smwb/onreel-git-mcp (часть E выделения, R-001).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/builtin.lib.ts — дословная копия. Регистрация была побочным эффектом импорта\n// guard.lib (onreel); в библиотеке она — только явный вызов registerBuiltinTrackers(), идемпотентный.\nimport { githubTracker } from './github.lib.ts';\nimport { gitlabTracker } from './gitlab.lib.ts';\nimport { jiraTracker } from './jira.lib.ts';\nimport { localTracker } from './local.lib.ts';\nimport { registerTracker } from './registry.lib.ts';\nimport { sourcecraftTracker } from './sourcecraft.lib.ts';\n\n// Трекеры, которые библиотека поставляет сама (D-350). Новый трекер добавляется модулем с\n// `TrackerDefinition` и строкой здесь: реестр и адаптеры не меняются.\n\nlet registered = false;\n\nexport function registerBuiltinTrackers(): void {\n if (registered) return;\n registered = true;\n for (const definition of [localTracker(), sourcecraftTracker(), githubTracker(), gitlabTracker(), jiraTracker()]) registerTracker(definition);\n}\n","// Хранение токенов подключений трекеров библиотеки @smwb/onreel-git-mcp (часть E выделения, D-352).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/secrets.lib.ts — копия; шов журнала host заменён на SecretSink ядра\n// (kernel/log.types.ts): по умолчанию defaultSecretSink общего redactor'а ядра (kernel/redact.lib.ts),\n// потребитель со своим журналом подставляет свой приёмник. Регистрация секрета не обязательна\n// для работы хранилища — это подсказка для маскирования текстов ошибок и журналов.\nimport { mkdir, readFile, rename, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { defaultSecretSink } from '../kernel/redact.lib.ts';\nimport type { SecretSink } from '../kernel/log.types.ts';\nimport { TRACKER_SECRETS_FILE } from './tracker.const.ts';\nimport { isRecord } from './tracker.lib.ts';\n\n// Секреты подключений (D-352): токены по projectId в файле 0600 каталога данных потребителя. В хранилище\n// задач, ответы и журналы они не попадают: наружу идёт только признак «токен есть», а значение при чтении\n// и записи регистрируется в приёмнике секретов как известный секрет (D-194).\n\n/** Записи идут по одной: чтение-правка-запись двух подключений не затирает друг друга. */\nlet queue: Promise<unknown> = Promise.resolve();\n\nfunction exclusive<T>(task: () => Promise<T>): Promise<T> {\n const run = queue.then(task, task);\n queue = run.catch(() => undefined);\n return run;\n}\n\nasync function readAll(dataDir: string): Promise<Record<string, string>> {\n let raw: string;\n try {\n raw = await readFile(join(dataDir, TRACKER_SECRETS_FILE), 'utf8');\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT') return {};\n throw error;\n }\n const parsed: unknown = JSON.parse(raw);\n if (!isRecord(parsed)) return {};\n return Object.fromEntries(Object.entries(parsed).filter((entry): entry is [string, string] => typeof entry[1] === 'string'));\n}\n\nasync function writeAll(dataDir: string, secrets: Record<string, string>): Promise<void> {\n await mkdir(dataDir, { recursive: true, mode: 0o700 });\n const target = join(dataDir, TRACKER_SECRETS_FILE);\n const temp = `${target}.${String(process.pid)}.tmp`;\n await writeFile(temp, JSON.stringify(secrets), { mode: 0o600 });\n await rename(temp, target);\n}\n\n/** Токен проекта; undefined — не задан. Значение регистрируется в приёмнике секретов. */\nexport async function readTrackerToken(dataDir: string, projectId: string, sink: SecretSink = defaultSecretSink): Promise<string | undefined> {\n const token = (await readAll(dataDir))[projectId];\n if (token !== undefined) sink.register(token);\n return token;\n}\n\nexport function hasTrackerToken(dataDir: string, projectId: string): Promise<boolean> {\n return readAll(dataDir).then((secrets) => secrets[projectId] !== undefined);\n}\n\n/** Задаёт токен проекта; пустая строка убирает. */\nexport function writeTrackerToken(dataDir: string, projectId: string, token: string, sink: SecretSink = defaultSecretSink): Promise<void> {\n if (token !== '') sink.register(token);\n return exclusive(async () => {\n const secrets = await readAll(dataDir);\n if (token === '') delete secrets[projectId];\n else secrets[projectId] = token;\n await writeAll(dataDir, secrets);\n });\n}\n\nexport function deleteTrackerToken(dataDir: string, projectId: string, sink: SecretSink = defaultSecretSink): Promise<void> {\n return writeTrackerToken(dataDir, projectId, '', sink);\n}\n","// Помощники pull request-ов библиотеки @smwb/onreel-git-mcp — свои (#15).\nimport type { PullRequestAdapter } from './pull.types.ts';\nimport { TrackerError } from './tracker.lib.ts';\nimport type { AdapterContext, TrackerDefinition } from './tracker.types.ts';\n\n/** Адаптер PR трекера (D-005); трекер без раздела pulls — TrackerError('unsupported', 'Трекер <title> не ведёт pull request-ы.'). */\nexport function pullRequestAdapterOf(definition: TrackerDefinition, context: AdapterContext): PullRequestAdapter {\n if (definition.pulls === undefined) throw new TrackerError('unsupported', `Трекер ${definition.descriptor.title} не ведёт pull request-ы.`);\n return definition.pulls.create(context);\n}\n"],"mappings":"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","names":["DEFAULT_API","TARGET","NUMBER","LIST_SUBJECT","COMMENTS_SUBJECT","pageOf","patchBody","commentOf","stateFilter","TARGET","SHA","PULL_CAPABILITIES","pullOf","usedStatuses","pageOf","stateFilter","patchBody","commentOf","DEFAULT_URL","TARGET","IID","ORDER_BY","issueOf","pageOf","stateFilter","composeLabels","patchBody","commentOf","ISSUE_CAPABILITIES","toIssue","issueOf","params","body","record","commentOf","priorityName","ISSUE_CAPABILITIES","DEFAULT_API","TARGET","SHA","PULL_CAPABILITIES","pullOf","usedStatuses","matchesPage","nextOf","createBody","commentOf","DEFAULT_API","TARGET","SLUG","ISSUE_CAPABILITIES","toIssue","issueOf","nextOf","patchBody","commentOf"]}