@smwb/onreel-git-mcp 0.2.1 → 0.3.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.
- package/README.md +83 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/tracker/index.js +365 -36
- package/dist/tracker/index.js.map +1 -1
- package/dist/tracker/mapping.const.d.ts +2 -0
- package/dist/tracker/tracker.const.d.ts +12 -0
- package/dist/tracker/tracker.lib.d.ts +26 -1
- package/dist/tracker/tracker.types.d.ts +61 -2
- package/package.json +1 -1
|
@@ -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 — дословная копия.\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","// Чистые помощники адаптеров трекеров библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/tracker.lib.ts — дословная копия, импорт типов из среза контракта библиотеки.\nimport type { IssuePriority, IssueStatusCategory } from '../contract/contract.types.ts';\nimport type { 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","// Таблицы сопоставления статусов и приоритетов трекеров библиотеки @smwb/onreel-git-mcp (часть E выделения).\n// Происхождение — onreel @ b73407be076a5df73931d1340f70910ca13c908d:\n// src/host/tracker/mapping.const.ts — дословная копия, импорт типов из среза контракта библиотеки.\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/** Приоритеты 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).\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) {\n if (response.status === 404 && request.missingIsIssue === true) throw new TrackerError('unknown_issue', 'Задача не найдена в трекере.');\n const detail = redactSecretText(raw.replace(/\\s+/g, ' ').trim()).slice(0, TRACKER_ERROR_BODY_MAX);\n throw new TrackerError('failed', `Трекер ${hostOf(url)} ответил ${String(response.status)}${detail === '' ? '' : `: ${detail}`}.`);\n }\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/** Адрес без пути и параметров: в тексте ошибки секретам неоткуда взяться. */\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 — дословная копия, импорт типов из среза контракта библиотеки.\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 { TrackerError, isRecord, lookup, priorityName, requireTarget, stringList, text, toTimestamp } from './tracker.lib.ts';\nimport type { AdapterContext, IssuePatchInput, TrackerAdapter, TrackerDefinition } 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\nconst DEFAULT_API = 'https://api.github.com';\nconst TARGET = /^[\\w.-]+\\/[\\w.-]+$/;\nconst NUMBER = /^[1-9]\\d{0,14}$/;\n\nexport function githubTracker(): TrackerDefinition {\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),\n };\n}\n\nfunction createGithubAdapter({ connection, fetch }: AdapterContext): 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 root = `${baseUrl(connection.url, DEFAULT_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 const page = pageOf(query.cursor);\n const params = new URLSearchParams({ state: stateFilter(query.status), per_page: String(query.limit), page: String(page) });\n const { body, headers: responseHeaders } = await requestJson(`${root}?${params.toString()}`, { fetch, headers });\n const items = (Array.isArray(body) ? body : []).filter((item) => isRecord(item) && item.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(responseHeaders.get('link') ?? '') ? { nextCursor: String(page + 1) } : {}),\n };\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 const page = pageOf(query.cursor);\n const params = new URLSearchParams({ per_page: String(query.limit), page: String(page) });\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/** Метки записи: пользовательские плюс служебные для приоритета и «в работе». */\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 { TrackerError, isRecord, lookup, priorityName, requireTarget, stringList, text, toTimestamp } from './tracker.lib.ts';\nimport type { AdapterContext, 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\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 };\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 const page = pageOf(query.cursor);\n const params = new URLSearchParams({ state: stateFilter(query.status), per_page: String(query.limit), page: String(page), order_by: 'created_at', sort: 'desc' });\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 const page = pageOf(query.cursor);\n const params = new URLSearchParams({ sort: '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 // Системные заметки («изменил метку») — не комментарии.\n const items = (Array.isArray(body) ? body : []).filter((note) => isRecord(note) && note.system !== true).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 — дословная копия, импорт типов из среза контракта библиотеки.\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 { TrackerError, isRecord, lookup, requireTarget, stringList, text, toTimestamp } from './tracker.lib.ts';\nimport type { AdapterContext, IssuePatchInput, 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\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 };\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 const jql = listJql(project, query.status);\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 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: '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 items = Array.isArray(record.comments) ? record.comments : [];\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 + items.length < total && items.length > 0 ? { nextCursor: String(at + items.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 списка; undefined — запрошенные категории Jira не знает (результат пуст). */\nfunction listJql(project: string, status: readonly IssueStatusCategory[] | undefined): string | undefined {\n const base = `project = \"${project}\"`;\n if (status === undefined) return `${base} ORDER BY created DESC`;\n const names = status.flatMap((item) => CATEGORY_JQL[item] ?? []);\n return names.length === 0 ? undefined : `${base} AND statusCategory in (${names.join(', ')}) ORDER BY created DESC`;\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).\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 { TrackerError } from './tracker.lib.ts';\nimport type { AdapterContext, 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\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 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: (query) => {\n const page = store.listLocalIssues(projectId, { limit: query.limit, ...(query.cursor === undefined ? {} : { cursor: query.cursor }), ...(query.status === undefined ? {} : { status: query.status }) });\n return Promise.resolve({ items: page.items.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: (key, query) => {\n const page = store.listLocalComments(projectId, mustGet(key).number, { limit: query.limit, ...(query.cursor === undefined ? {} : { cursor: query.cursor }) });\n return Promise.resolve({ items: page.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\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 — дословная копия, импорт типов из среза контракта библиотеки.\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_SLUGS } from './mapping.const.ts';\nimport { TrackerError, isRecord, lookup, requireTarget, stringList, text, toTimestamp } from './tracker.lib.ts';\nimport type { AdapterContext, IssuePatchInput, 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\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 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 const params = new URLSearchParams({ page_size: String(query.limit) });\n if (query.cursor !== undefined) params.set('page_token', query.cursor);\n const { body } = await requestJson(`${root}?${params.toString()}`, { fetch, headers });\n const record = isRecord(body) ? body : {};\n const issues = (Array.isArray(record.issues) ? record.issues : []).map(toIssue);\n return { items: query.status === undefined ? issues : issues.filter((issue) => query.status?.includes(issue.status.category) === true), ...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 const params = new URLSearchParams({ page_size: String(query.limit) });\n if (query.cursor !== undefined) params.set('page_token', query.cursor);\n const { body } = await requestJson(`${root}/${slug(key)}/comments?${params.toString()}`, { fetch, headers, missingIsIssue: true });\n const record = isRecord(body) ? body : {};\n return { items: (Array.isArray(record.issue_comments) ? record.issue_comments : []).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\nfunction nextOf(token: unknown): { nextCursor?: string } {\n const value = text(token);\n return value === undefined ? {} : { nextCursor: value };\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","toIssue","issueOf","params","body","record","commentOf","priorityName","DEFAULT_API","TARGET","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/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"]}
|
|
@@ -3,6 +3,8 @@ import type { IssuePriority, IssueStatusCategory } from '../contract/contract.ty
|
|
|
3
3
|
export declare const SOURCECRAFT_STATUSES: Readonly<Record<string, IssueStatusCategory>>;
|
|
4
4
|
/** Категория → слаг статуса SourceCraft при переводе задачи. */
|
|
5
5
|
export declare const SOURCECRAFT_STATUS_SLUGS: Readonly<Record<IssueStatusCategory, string>>;
|
|
6
|
+
/** Категория → слаги статусов QL фильтра списка (`status in (…)`); QL принимает только слаги, не имена. */
|
|
7
|
+
export declare const SOURCECRAFT_STATUS_FILTER: Readonly<Record<IssueStatusCategory, readonly string[]>>;
|
|
6
8
|
/** Приоритеты SourceCraft совпадают с единой моделью по именам. */
|
|
7
9
|
export declare const SOURCECRAFT_PRIORITIES: Readonly<Record<string, IssuePriority>>;
|
|
8
10
|
/** Jira: `statusCategory.key` статуса. */
|