@xdevops/issue-auto-finish 1.0.60 → 1.0.62

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.
Files changed (61) hide show
  1. package/dist/ai-runner/AIRunner.d.ts +5 -0
  2. package/dist/ai-runner/AIRunner.d.ts.map +1 -1
  3. package/dist/ai-runner/CodebuddyAcpRunner.d.ts +23 -0
  4. package/dist/ai-runner/CodebuddyAcpRunner.d.ts.map +1 -0
  5. package/dist/ai-runner/ModelMapping.d.ts.map +1 -1
  6. package/dist/ai-runner/acp/AcpProtocol.d.ts +98 -0
  7. package/dist/ai-runner/acp/AcpProtocol.d.ts.map +1 -0
  8. package/dist/ai-runner/index.d.ts +2 -1
  9. package/dist/ai-runner/index.d.ts.map +1 -1
  10. package/dist/{ai-runner-V5W2MNKT.js → ai-runner-DHH74B4O.js} +5 -3
  11. package/dist/{analyze-66JTH5BU.js → analyze-F5DFTM2A.js} +4 -4
  12. package/dist/{braindump-V2H26LEJ.js → braindump-JZ2CJC2I.js} +5 -5
  13. package/dist/{chunk-TZLOODIV.js → chunk-4D5GYH4P.js} +5 -3
  14. package/dist/chunk-4D5GYH4P.js.map +1 -0
  15. package/dist/{chunk-GT2ORJP5.js → chunk-BXCTN44G.js} +46 -4
  16. package/dist/chunk-BXCTN44G.js.map +1 -0
  17. package/dist/chunk-DADQSKPL.js +1 -0
  18. package/dist/{chunk-WNKWJZ3S.js → chunk-MSZQ3T4G.js} +2 -2
  19. package/dist/{chunk-OXTGJ5K6.js → chunk-NKJGLRZS.js} +2 -2
  20. package/dist/{chunk-DLNHF36B.js → chunk-NPCR4ZNN.js} +20 -15
  21. package/dist/chunk-NPCR4ZNN.js.map +1 -0
  22. package/dist/{chunk-EC5BMIE5.js → chunk-TASSKSJ3.js} +456 -1
  23. package/dist/chunk-TASSKSJ3.js.map +1 -0
  24. package/dist/{chunk-INTPETTB.js → chunk-WBHUOIEV.js} +4 -4
  25. package/dist/cli.js +7 -7
  26. package/dist/{config-2FWA2C7M.js → config-U4BU2FHH.js} +3 -3
  27. package/dist/config-schema.d.ts +2 -0
  28. package/dist/config-schema.d.ts.map +1 -1
  29. package/dist/config.d.ts +2 -0
  30. package/dist/config.d.ts.map +1 -1
  31. package/dist/coordination/IssueClaimer.d.ts +4 -0
  32. package/dist/coordination/IssueClaimer.d.ts.map +1 -1
  33. package/dist/index.js +7 -7
  34. package/dist/{init-D7WC4CM5.js → init-USNTJBIC.js} +4 -4
  35. package/dist/lib.js +4 -4
  36. package/dist/phases/BasePhase.d.ts +7 -1
  37. package/dist/phases/BasePhase.d.ts.map +1 -1
  38. package/dist/poller/IssuePoller.d.ts.map +1 -1
  39. package/dist/{restart-U4XXBQX5.js → restart-RUY67743.js} +4 -4
  40. package/dist/run.js +7 -7
  41. package/dist/{start-3ISG2D4L.js → start-DPGDJHIM.js} +4 -4
  42. package/package.json +1 -1
  43. package/src/web/frontend/dist/assets/{index-CNr_jnFX.css → index-BqzWCv1L.css} +1 -1
  44. package/src/web/frontend/dist/assets/{index-CsJhieIu.js → index-RawqoOth.js} +3 -3
  45. package/src/web/frontend/dist/index.html +2 -2
  46. package/dist/chunk-DLNHF36B.js.map +0 -1
  47. package/dist/chunk-EC5BMIE5.js.map +0 -1
  48. package/dist/chunk-GT2ORJP5.js.map +0 -1
  49. package/dist/chunk-RQUJ4UEW.js +0 -1
  50. package/dist/chunk-TZLOODIV.js.map +0 -1
  51. /package/dist/{ai-runner-V5W2MNKT.js.map → ai-runner-DHH74B4O.js.map} +0 -0
  52. /package/dist/{analyze-66JTH5BU.js.map → analyze-F5DFTM2A.js.map} +0 -0
  53. /package/dist/{braindump-V2H26LEJ.js.map → braindump-JZ2CJC2I.js.map} +0 -0
  54. /package/dist/{chunk-RQUJ4UEW.js.map → chunk-DADQSKPL.js.map} +0 -0
  55. /package/dist/{chunk-WNKWJZ3S.js.map → chunk-MSZQ3T4G.js.map} +0 -0
  56. /package/dist/{chunk-OXTGJ5K6.js.map → chunk-NKJGLRZS.js.map} +0 -0
  57. /package/dist/{chunk-INTPETTB.js.map → chunk-WBHUOIEV.js.map} +0 -0
  58. /package/dist/{config-2FWA2C7M.js.map → config-U4BU2FHH.js.map} +0 -0
  59. /package/dist/{init-D7WC4CM5.js.map → init-USNTJBIC.js.map} +0 -0
  60. /package/dist/{restart-U4XXBQX5.js.map → restart-RUY67743.js.map} +0 -0
  61. /package/dist/{start-3ISG2D4L.js.map → start-DPGDJHIM.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/clients/GongfengClient.ts","../src/utils/CircuitBreaker.ts","../src/utils/RetryPolicy.ts","../src/tracker/IssueState.ts","../src/tracker/IssueTracker.ts","../src/persistence/PlanPersistence.ts","../src/phases/BasePhase.ts","../src/rules/RuleResolver.ts","../src/notesync/NoteSyncSettings.ts","../src/phases/VerifyPhase.ts","../src/verify/VerifyReportParser.ts","../src/phases/PlanPhase.ts","../src/phases/BuildPhase.ts","../src/phases/PhaseFactory.ts","../src/lifecycle/ActionLifecycleManager.ts","../src/pipeline/PipelineDefinition.ts","../src/orchestrator/PipelineOrchestrator.ts","../src/demand/adapters/GongfengAdapter.ts","../src/utils/MergeRequestHelper.ts","../src/deploy/PortAllocator.ts","../src/deploy/DevServerManager.ts","../src/e2e/E2eSettings.ts","../src/e2e/ScreenshotCollector.ts","../src/e2e/ScreenshotPublisher.ts","../src/metrics/MetricsCollector.ts","../src/orchestrator/steps/SetupStep.ts","../src/orchestrator/steps/PhaseLoopStep.ts","../src/orchestrator/steps/CompletionStep.ts","../src/orchestrator/steps/FailureHandler.ts","../src/services/BrainstormService.ts","../src/prompts/brainstorm-templates.ts"],"sourcesContent":["import fs from 'node:fs';\nimport path from 'node:path';\nimport { GongfengApiError, GongfengUploadError } from '../errors/index.js';\nimport { logger as rootLogger } from '../logger.js';\nimport { CircuitBreaker } from '../utils/CircuitBreaker.js';\nimport { RetryPolicy } from '../utils/RetryPolicy.js';\n\nconst logger = rootLogger.child('GongfengClient');\n\nexport interface GongfengIssue {\n id: number;\n iid: number;\n title: string;\n description: string;\n state: string;\n labels: string[];\n created_at: string;\n updated_at: string;\n author: { username: string; name: string };\n /** 工蜂 API 返回的负责人列表(字段名可能是 assignees 或 assignee_users) */\n assignees?: Array<{ username: string; name: string }>;\n assignee_users?: Array<{ username: string; name: string }>;\n}\n\nexport interface GongfengUser {\n id: number;\n username: string;\n name: string;\n}\n\nexport interface GongfengConfig {\n apiUrl: string;\n privateToken: string;\n projectPath: string;\n}\n\nexport interface CreateMergeRequestOptions {\n sourceBranch: string;\n targetBranch: string;\n title: string;\n description?: string;\n}\n\nexport interface GongfengMergeRequest {\n id: number;\n iid: number;\n title: string;\n web_url: string;\n state: string;\n source_branch?: string;\n target_branch?: string;\n}\n\nexport interface GongfengMergeRequestDetail extends GongfengMergeRequest {\n has_conflicts: boolean;\n merge_status: string;\n}\n\nexport interface UploadResult {\n alt: string;\n url: string;\n markdown: string;\n}\n\nexport interface GongfengNote {\n id: number;\n body: string;\n author: { username: string; name: string };\n created_at: string;\n}\n\nexport const AGENT_NOTE_MARKER = '\\n\\n<!-- issue-auto-finish-agent -->';\nconst AGENT_NOTE_MARKER_PATTERN = '<!-- issue-auto-finish-agent -->';\n\nexport class GongfengClient {\n private apiUrl: string;\n private token: string;\n private projectPath: string;\n private readonly retryPolicy: RetryPolicy;\n private readonly circuitBreaker: CircuitBreaker;\n\n constructor(config: GongfengConfig) {\n this.apiUrl = config.apiUrl.replace(/\\/$/, '');\n this.token = config.privateToken;\n this.projectPath = config.projectPath;\n\n this.retryPolicy = new RetryPolicy({\n maxRetries: 3,\n baseDelayMs: 1000,\n maxDelayMs: 30000,\n jitterFactor: 0.2,\n isRetryable: (err: unknown) => {\n if (err instanceof GongfengApiError) {\n return err.isRetryable;\n }\n // Network errors (e.g. fetch failures) are retryable\n if (err instanceof TypeError && (err.message.includes('fetch') || err.message.includes('network'))) {\n return true;\n }\n return false;\n },\n });\n\n this.circuitBreaker = new CircuitBreaker('GongfengAPI', {\n failureThreshold: 5,\n resetTimeoutMs: 60000,\n successThreshold: 2,\n });\n }\n\n private get projectApiBase(): string {\n const encoded = encodeURIComponent(this.projectPath);\n return `${this.apiUrl}/api/v3/projects/${encoded}`;\n }\n\n private async requestRaw(path: string, options: RequestInit = {}): Promise<Response> {\n const url = `${this.projectApiBase}${path}`;\n logger.debug('API request', { method: options.method || 'GET', url });\n\n return this.circuitBreaker.execute(() =>\n this.retryPolicy.execute(async () => {\n const resp = await fetch(url, {\n ...options,\n headers: {\n 'PRIVATE-TOKEN': this.token,\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n });\n\n if (!resp.ok) {\n const body = await resp.text();\n throw new GongfengApiError(resp.status, `Gongfeng API error ${resp.status}: ${body}`, body);\n }\n\n return resp;\n }, `requestRaw ${options.method || 'GET'} ${path}`),\n );\n }\n\n private async request<T>(path: string, options: RequestInit = {}): Promise<T> {\n const resp = await this.requestRaw(path, options);\n return resp.json() as Promise<T>;\n }\n\n async createIssue(\n title: string,\n description: string,\n labels?: string[],\n ): Promise<GongfengIssue> {\n const body: Record<string, string> = { title, description };\n if (labels && labels.length > 0) {\n body.labels = labels.join(',');\n }\n const issue = await this.request<GongfengIssue>('/issues', {\n method: 'POST',\n body: JSON.stringify(body),\n });\n logger.info('Issue created', { id: issue.id, iid: issue.iid, title });\n return issue;\n }\n\n async listIssues(state: string = 'opened', labels?: string): Promise<GongfengIssue[]> {\n const params = new URLSearchParams({ state, per_page: '100' });\n if (labels) {\n params.set('labels', labels);\n }\n return this.request<GongfengIssue[]>(`/issues?${params.toString()}`);\n }\n\n async listIssuesAdvanced(options: {\n state?: string;\n labels?: string;\n search?: string;\n page?: number;\n perPage?: number;\n } = {}): Promise<{ issues: GongfengIssue[]; total: number }> {\n const params = new URLSearchParams({\n state: options.state || 'opened',\n page: String(options.page || 1),\n per_page: String(options.perPage || 20),\n });\n if (options.labels) {\n params.set('labels', options.labels);\n }\n if (options.search) {\n params.set('search', options.search);\n }\n const resp = await this.requestRaw(`/issues?${params.toString()}`);\n const total = parseInt(resp.headers.get('x-total') || '0', 10);\n const issues = (await resp.json()) as GongfengIssue[];\n return { issues, total: total || issues.length };\n }\n\n async getIssueDetail(issueId: number): Promise<GongfengIssue> {\n return this.request<GongfengIssue>(`/issues/${issueId}`);\n }\n\n async createIssueNote(issueId: number, body: string): Promise<void> {\n const markedBody = body + AGENT_NOTE_MARKER;\n await this.request(`/issues/${issueId}/notes`, {\n method: 'POST',\n body: JSON.stringify({ body: markedBody }),\n });\n logger.info('Issue note created', { issueId });\n }\n\n async updateIssueLabels(issueId: number, labels: string[]): Promise<void> {\n await this.request(`/issues/${issueId}`, {\n method: 'PUT',\n body: JSON.stringify({ labels: labels.join(',') }),\n });\n logger.info('Issue labels updated', { issueId, labels });\n }\n\n async createMergeRequest(options: CreateMergeRequestOptions): Promise<GongfengMergeRequest> {\n const mr = await this.request<GongfengMergeRequest>('/merge_requests', {\n method: 'POST',\n body: JSON.stringify({\n source_branch: options.sourceBranch,\n target_branch: options.targetBranch,\n title: options.title,\n description: options.description ?? '',\n }),\n });\n if (!mr.web_url && mr.iid) {\n mr.web_url = this.buildMergeRequestUrl(mr.iid);\n }\n logger.info('Merge request created', { iid: mr.iid, webUrl: mr.web_url });\n return mr;\n }\n\n async findMergeRequestByBranch(\n sourceBranch: string,\n targetBranch: string,\n state: string = 'opened',\n ): Promise<GongfengMergeRequest | null> {\n const params = new URLSearchParams({\n state,\n source_branch: sourceBranch,\n target_branch: targetBranch,\n });\n const mrs = await this.request<GongfengMergeRequest[]>(\n `/merge_requests?${params.toString()}`,\n );\n if (mrs.length === 0) return null;\n const mr = mrs[0];\n if (!mr.web_url && mr.iid) {\n mr.web_url = this.buildMergeRequestUrl(mr.iid);\n }\n return mr;\n }\n\n private buildMergeRequestUrl(mrIid: number): string {\n return `${this.apiUrl}/${this.projectPath}/merge_requests/${mrIid}`;\n }\n\n async uploadFile(filePath: string): Promise<UploadResult> {\n const fileData = fs.readFileSync(filePath);\n const fileName = path.basename(filePath);\n const mimeType = fileName.endsWith('.png') ? 'image/png' : 'application/octet-stream';\n const blob = new Blob([fileData], { type: mimeType });\n\n const formData = new FormData();\n formData.append('file', blob, fileName);\n\n const url = `${this.projectApiBase}/uploads`;\n logger.debug('Upload request', { url, fileName });\n\n const resp = await fetch(url, {\n method: 'POST',\n headers: { 'PRIVATE-TOKEN': this.token },\n body: formData,\n });\n\n if (!resp.ok) {\n const body = await resp.text();\n throw new GongfengUploadError(resp.status, `Gongfeng upload error ${resp.status}: ${body}`, body);\n }\n\n const result = (await resp.json()) as UploadResult;\n logger.info('File uploaded', { fileName, url: result.url });\n return result;\n }\n\n async createMergeRequestNote(mrIid: number, body: string): Promise<void> {\n const markedBody = body + AGENT_NOTE_MARKER;\n await this.request(`/merge_requests/${mrIid}/notes`, {\n method: 'POST',\n body: JSON.stringify({ body: markedBody }),\n });\n logger.info('Merge request note created', { mrIid });\n }\n\n async closeMergeRequest(mrIid: number): Promise<void> {\n await this.request(`/merge_requests/${mrIid}`, {\n method: 'PUT',\n body: JSON.stringify({ state_event: 'close' }),\n });\n logger.info('Merge request closed', { mrIid });\n }\n\n async deleteIssue(issueId: number): Promise<void> {\n await this.request(`/issues/${issueId}`, { method: 'DELETE' });\n logger.info('Issue deleted', { issueId });\n }\n\n async closeIssue(issueId: number): Promise<void> {\n await this.request(`/issues/${issueId}`, {\n method: 'PUT',\n body: JSON.stringify({ state_event: 'close', labels: 'auto-finish:e2e-cleaned' }),\n });\n logger.info('Issue closed', { issueId });\n }\n\n async listIssueNotes(issueId: number): Promise<GongfengNote[]> {\n const allNotes: GongfengNote[] = [];\n let page = 1;\n while (true) {\n const params = new URLSearchParams({ per_page: '100', page: String(page) });\n const batch = await this.request<GongfengNote[]>(\n `/issues/${issueId}/notes?${params.toString()}`,\n );\n allNotes.push(...batch);\n if (batch.length < 100) break;\n page++;\n }\n return allNotes;\n }\n\n async deleteIssueNote(issueId: number, noteId: number): Promise<void> {\n // 工蜂 API 不支持 DELETE notes (返回 405),改用 PUT 清空内容使其失效(软删除)\n await this.request(`/issues/${issueId}/notes/${noteId}`, {\n method: 'PUT',\n body: JSON.stringify({ body: '<!-- iaf-note-deleted -->' }),\n });\n logger.debug('Issue note invalidated (soft-delete)', { issueId, noteId });\n }\n\n async cleanupAgentNotes(issueId: number): Promise<number> {\n const notes = await this.listIssueNotes(issueId);\n const agentNotes = notes.filter(n => n.body.includes(AGENT_NOTE_MARKER_PATTERN));\n for (const note of agentNotes) {\n await this.deleteIssueNote(issueId, note.id);\n }\n if (agentNotes.length > 0) {\n logger.info('Agent notes cleaned up', { issueId, deleted: agentNotes.length });\n }\n return agentNotes.length;\n }\n\n async getMergeRequestDetail(mrIid: number): Promise<GongfengMergeRequestDetail> {\n const mr = await this.request<GongfengMergeRequestDetail>(`/merge_requests/${mrIid}`);\n if (!mr.web_url && mr.iid) {\n mr.web_url = this.buildMergeRequestUrl(mr.iid);\n }\n return mr;\n }\n\n private async requestGlobal<T>(path: string, options: RequestInit = {}): Promise<T> {\n const url = `${this.apiUrl}${path}`;\n logger.debug('API request (global)', { method: options.method || 'GET', url });\n\n const resp = await this.circuitBreaker.execute(() =>\n this.retryPolicy.execute(async () => {\n const r = await fetch(url, {\n ...options,\n headers: {\n 'PRIVATE-TOKEN': this.token,\n 'Content-Type': 'application/json',\n ...options.headers,\n },\n });\n\n if (!r.ok) {\n const body = await r.text();\n throw new GongfengApiError(r.status, `Gongfeng API error ${r.status}: ${body}`, body);\n }\n\n return r;\n }, `requestGlobal ${options.method || 'GET'} ${path}`),\n );\n\n return resp.json() as Promise<T>;\n }\n\n /** 获取当前 Token 对应的用户信息 */\n async getCurrentUser(): Promise<GongfengUser> {\n return this.requestGlobal<GongfengUser>('/api/v3/user');\n }\n\n /** 设置 Issue 负责人 */\n async setIssueAssignee(issueId: number, username: string): Promise<void> {\n await this.request(`/issues/${issueId}`, {\n method: 'PUT',\n body: JSON.stringify({ assignee_users: username }),\n });\n logger.info('Issue assignee updated', { issueId, username });\n }\n\n /** 清除 Issue 负责人 */\n async clearIssueAssignee(issueId: number): Promise<void> {\n await this.request(`/issues/${issueId}`, {\n method: 'PUT',\n body: JSON.stringify({ assignee_users: '' }),\n });\n logger.info('Issue assignee cleared', { issueId });\n }\n\n /** 更新 Issue 评论内容(用于心跳刷新锁评论) */\n async updateIssueNote(issueId: number, noteId: number, body: string): Promise<void> {\n await this.request(`/issues/${issueId}/notes/${noteId}`, {\n method: 'PUT',\n body: JSON.stringify({ body }),\n });\n logger.debug('Issue note updated', { issueId, noteId });\n }\n\n /** 创建 Issue 评论(不带 AGENT_NOTE_MARKER),返回含 id 的 note */\n async createIssueNotePlain(issueId: number, body: string): Promise<GongfengNote> {\n const note = await this.request<GongfengNote>(`/issues/${issueId}/notes`, {\n method: 'POST',\n body: JSON.stringify({ body }),\n });\n logger.debug('Issue note created (plain)', { issueId, noteId: note.id });\n return note;\n }\n\n /** Update connection config at runtime (for hot-reload) */\n updateConfig(config: GongfengConfig): void {\n this.apiUrl = config.apiUrl.replace(/\\/$/, '');\n this.token = config.privateToken;\n this.projectPath = config.projectPath;\n logger.info('GongfengClient config updated', { apiUrl: this.apiUrl, projectPath: this.projectPath });\n }\n\n /** 移除指定前缀的所有标签(精确匹配 prefix 和 prefix:* 前缀) */\n async removeLabelsWithPrefix(issueId: number, prefix: string): Promise<void> {\n const issue = await this.getIssueDetail(issueId);\n const filtered = issue.labels.filter(l => l !== prefix && !l.startsWith(prefix + ':'));\n if (filtered.length === issue.labels.length) return; // 没有需要移除的标签\n await this.updateIssueLabels(issueId, filtered);\n }\n\n async addLabel(issueId: number, label: string): Promise<void> {\n const issue = await this.getIssueDetail(issueId);\n if (issue.labels.includes(label)) {\n logger.info('Label already exists, skipping', { issueId, label });\n return;\n }\n const newLabels = [...issue.labels, label];\n await this.updateIssueLabels(issueId, newLabels);\n }\n}\n","import { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('CircuitBreaker');\n\nexport enum CircuitState {\n Closed = 'closed',\n Open = 'open',\n HalfOpen = 'half-open',\n}\n\nexport interface CircuitBreakerOptions {\n /** Number of failures before opening (default: 5) */\n failureThreshold?: number;\n /** Time in ms before trying half-open (default: 60000) */\n resetTimeoutMs?: number;\n /** Number of successes needed to close from half-open (default: 2) */\n successThreshold?: number;\n}\n\nexport class CircuitBreaker {\n private state: CircuitState = CircuitState.Closed;\n private failureCount = 0;\n private successCount = 0;\n private lastFailureTime = 0;\n private readonly failureThreshold: number;\n private readonly resetTimeoutMs: number;\n private readonly successThreshold: number;\n\n constructor(\n private readonly name: string,\n options?: CircuitBreakerOptions,\n ) {\n this.failureThreshold = options?.failureThreshold ?? 5;\n this.resetTimeoutMs = options?.resetTimeoutMs ?? 60000;\n this.successThreshold = options?.successThreshold ?? 2;\n }\n\n getState(): CircuitState {\n return this.state;\n }\n\n async execute<T>(fn: () => Promise<T>): Promise<T> {\n if (this.state === CircuitState.Open) {\n if (Date.now() - this.lastFailureTime >= this.resetTimeoutMs) {\n this.transitionTo(CircuitState.HalfOpen);\n } else {\n throw new Error(`Circuit breaker '${this.name}' is open`);\n }\n }\n\n try {\n const result = await fn();\n this.onSuccess();\n return result;\n } catch (err) {\n this.onFailure();\n throw err;\n }\n }\n\n /** Reset to closed state (e.g., for testing or manual recovery) */\n reset(): void {\n this.failureCount = 0;\n this.successCount = 0;\n this.lastFailureTime = 0;\n this.transitionTo(CircuitState.Closed);\n }\n\n private onSuccess(): void {\n if (this.state === CircuitState.HalfOpen) {\n this.successCount++;\n if (this.successCount >= this.successThreshold) {\n this.transitionTo(CircuitState.Closed);\n }\n } else {\n // In closed state, reset failure count on success\n this.failureCount = 0;\n }\n }\n\n private onFailure(): void {\n this.failureCount++;\n this.lastFailureTime = Date.now();\n\n if (this.state === CircuitState.HalfOpen) {\n // Any failure in half-open goes back to open\n this.transitionTo(CircuitState.Open);\n } else if (this.failureCount >= this.failureThreshold) {\n this.transitionTo(CircuitState.Open);\n }\n }\n\n private transitionTo(newState: CircuitState): void {\n if (this.state === newState) return;\n const oldState = this.state;\n this.state = newState;\n\n if (newState === CircuitState.Closed) {\n this.failureCount = 0;\n this.successCount = 0;\n } else if (newState === CircuitState.HalfOpen) {\n this.successCount = 0;\n }\n\n logger.info('Circuit breaker state transition', {\n name: this.name,\n from: oldState,\n to: newState,\n });\n }\n}\n","import { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('RetryPolicy');\n\nexport interface RetryPolicyOptions {\n /** Maximum number of retry attempts (default: 3) */\n maxRetries?: number;\n /** Initial delay in ms (default: 1000) */\n baseDelayMs?: number;\n /** Maximum delay in ms (default: 30000) */\n maxDelayMs?: number;\n /** Jitter factor 0-1 (default: 0.2) */\n jitterFactor?: number;\n /** Function to determine if error is retryable */\n isRetryable?: (error: unknown) => boolean;\n}\n\nexport class RetryPolicy {\n private readonly maxRetries: number;\n private readonly baseDelayMs: number;\n private readonly maxDelayMs: number;\n private readonly jitterFactor: number;\n private readonly isRetryable: (error: unknown) => boolean;\n\n constructor(options?: RetryPolicyOptions) {\n this.maxRetries = options?.maxRetries ?? 3;\n this.baseDelayMs = options?.baseDelayMs ?? 1000;\n this.maxDelayMs = options?.maxDelayMs ?? 30000;\n this.jitterFactor = options?.jitterFactor ?? 0.2;\n this.isRetryable = options?.isRetryable ?? (() => true);\n }\n\n /** Execute fn with retry. Returns the result or throws the last error. */\n async execute<T>(fn: () => Promise<T>, context?: string): Promise<T> {\n let lastError: unknown;\n for (let attempt = 0; attempt <= this.maxRetries; attempt++) {\n try {\n return await fn();\n } catch (err) {\n lastError = err;\n if (attempt >= this.maxRetries || !this.isRetryable(err)) {\n throw err;\n }\n const delay = this.calculateDelay(attempt);\n logger.warn('Retrying after error', {\n context,\n attempt: attempt + 1,\n maxRetries: this.maxRetries,\n delayMs: delay,\n error: (err as Error).message,\n });\n await this.sleep(delay);\n }\n }\n throw lastError; // unreachable but satisfies TS\n }\n\n private calculateDelay(attempt: number): number {\n // Exponential backoff: base * 2^attempt\n const exponential = this.baseDelayMs * Math.pow(2, attempt);\n const capped = Math.min(exponential, this.maxDelayMs);\n // Add jitter\n const jitter = capped * this.jitterFactor * (Math.random() * 2 - 1);\n return Math.max(0, Math.round(capped + jitter));\n }\n\n private sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n}\n","import type { DemandSpec } from '../demand/DemandSpec.js';\n\nexport enum IssueState {\n Pending = 'pending',\n Skipped = 'skipped',\n BranchCreated = 'branch_created',\n // ── 通用阶段状态 ──\n /** AI 阶段执行中(配合 currentPhase 使用) */\n PhaseRunning = 'phase_running',\n /** AI 阶段执行完毕(配合 currentPhase 使用) */\n PhaseDone = 'phase_done',\n /** Gate 阶段等待中(配合 currentPhase 使用) */\n PhaseWaiting = 'phase_waiting',\n /** Gate 阶段已批准(配合 currentPhase 使用) */\n PhaseApproved = 'phase_approved',\n // Conflict resolution (post-completion)\n ResolvingConflict = 'resolving_conflict',\n // Terminal\n Completed = 'completed',\n Failed = 'failed',\n}\n\nexport type PipelineMode = string;\n\nexport interface PortPairRecord {\n backendPort: number;\n frontendPort: number;\n}\n\n/** 生命周期状态 — 由 IssueTracker 管理 */\nexport interface IssueLifecycle {\n state: IssueState;\n /** 当 state 为 PhaseRunning/PhaseDone/PhaseWaiting/PhaseApproved 时,记录具体阶段名 */\n currentPhase?: string;\n attempts: number;\n lastError?: string;\n failedAtState?: IssueState;\n}\n\n/** 流水线配置 */\nexport interface IssuePipeline {\n pipelineMode?: PipelineMode;\n}\n\n/** 分支信息 */\nexport interface IssueBranch {\n branchName: string;\n}\n\n/** Issue 级别的功能开关 */\nexport interface IssueFeatureFlags {\n /** undefined = follow system setting */\n issueNoteSyncEnabled?: boolean;\n /** undefined = follow system setting */\n e2eEnabled?: boolean;\n}\n\n/** 部署/预览信息 */\nexport interface IssueDeployment {\n /** Allocated ports for preview/E2E (persisted for recovery) */\n ports?: PortPairRecord;\n /** Preview servers started at */\n previewStartedAt?: string;\n}\n\n/** 结果信息 */\nexport interface IssueResult {\n mrUrl?: string;\n}\n\n/** 审计时间戳 */\nexport interface IssueAudit {\n createdAt: string;\n updatedAt: string;\n}\n\n/** 需求规格(知识域),新建 Issue 时填充 */\nexport interface IssueDemand {\n demandSpec?: DemandSpec;\n}\n\n/** 完整的 IssueRecord — 持久化格式不变 */\nexport type IssueRecord =\n IssueLifecycle &\n IssuePipeline &\n IssueBranch &\n IssueFeatureFlags &\n IssueDeployment &\n IssueResult &\n IssueDemand &\n IssueAudit;\n\nexport type PhaseStatus = 'pending' | 'in_progress' | 'completed' | 'failed';\n\nexport interface PhaseProgress {\n status: PhaseStatus;\n startedAt?: string;\n completedAt?: string;\n error?: string;\n}\n\nexport interface ProgressData {\n displayId: number;\n title: string;\n branchName: string;\n pipelineMode?: PipelineMode;\n currentPhase: string;\n phases: Record<string, PhaseProgress>;\n}\n","import { IssueRecord, IssueState } from './IssueState.js';\nimport { type PipelineDef } from '../pipeline/PipelineDefinition.js';\nimport { IssueNotFoundError } from '../errors/index.js';\nimport { ActionLifecycleManager } from '../lifecycle/ActionLifecycleManager.js';\nimport { BaseTracker } from './BaseTracker.js';\nimport { type ExecutableTask, issueToExecutableTask } from './ExecutableTask.js';\nimport { getIid } from './IssueRecordHelper.js';\nimport { logger as rootLogger } from '../logger.js';\nimport { eventBus } from '../events/EventBus.js';\n\nconst logger = rootLogger.child('IssueTracker');\n\n/**\n * 旧阶段专属状态 → 通用状态的映射表。\n * 使用字符串字面量,不引用 IssueState 枚举(删枚举后不受影响)。\n */\nconst STATE_MIGRATION_MAP: Record<string, { state: string; currentPhase: string }> = {\n analyzing: { state: 'phase_running', currentPhase: 'analysis' },\n analysis_done: { state: 'phase_done', currentPhase: 'analysis' },\n designing: { state: 'phase_running', currentPhase: 'design' },\n design_done: { state: 'phase_done', currentPhase: 'design' },\n implementing: { state: 'phase_running', currentPhase: 'implement' },\n implement_done: { state: 'phase_done', currentPhase: 'implement' },\n planning: { state: 'phase_running', currentPhase: 'plan' },\n plan_done: { state: 'phase_done', currentPhase: 'plan' },\n building: { state: 'phase_running', currentPhase: 'build' },\n build_done: { state: 'phase_done', currentPhase: 'build' },\n verifying: { state: 'phase_running', currentPhase: 'verify' },\n // 旧 gate 硬编码状态 → 通用 gate 状态\n waiting_for_review: { state: 'phase_waiting', currentPhase: 'review' },\n review_approved: { state: 'phase_approved', currentPhase: 'review' },\n};\n\nexport class IssueTracker extends BaseTracker<IssueRecord> {\n private lifecycleManagers: Map<string, ActionLifecycleManager>;\n\n constructor(dataDir: string, lifecycleManagers: Map<string, ActionLifecycleManager>) {\n super(dataDir, 'tracker.json', 'issues', 'tracker');\n this.lifecycleManagers = lifecycleManagers;\n this.migrateRecords();\n }\n\n /**\n * 迁移旧格式记录到新格式:\n * 1. 旧阶段专属状态 → PhaseRunning/PhaseDone + currentPhase\n * 2. failedAtState 同步迁移\n * 3. 为缺少 demandSpec 的旧记录回填\n *\n * 幂等:已迁移的记录不会重复处理。\n */\n private migrateRecords(): void {\n let migrated = 0;\n for (const record of this.getAllRecords()) {\n const raw = record as unknown as Record<string, unknown>;\n\n // 1. 迁移主状态\n const stateStr = raw.state as string;\n const migration = STATE_MIGRATION_MAP[stateStr];\n if (migration) {\n raw.state = migration.state;\n raw.currentPhase = migration.currentPhase;\n migrated++;\n }\n\n // 2. 迁移 failedAtState\n const failedAtStr = raw.failedAtState as string | undefined;\n if (failedAtStr) {\n const failedMigration = STATE_MIGRATION_MAP[failedAtStr];\n if (failedMigration) {\n raw.failedAtState = failedMigration.state;\n // 如果 failedAtState 迁移了,也需要记录 currentPhase(除非主状态已设置)\n if (!raw.currentPhase) {\n raw.currentPhase = failedMigration.currentPhase;\n }\n }\n }\n\n // 3. 回填 demandSpec(兼容旧记录)\n if (!raw.demandSpec && raw.issueIid) {\n raw.demandSpec = {\n demandId: `gf-${raw.issueIid}`,\n sourceRef: {\n source: 'gongfeng-issue',\n externalId: String(raw.issueId ?? raw.issueIid),\n displayId: String(raw.issueIid),\n },\n title: (raw.issueTitle as string) || '',\n description: '',\n createdAt: (raw.createdAt as string) || new Date().toISOString(),\n };\n }\n\n // 4. 删除 IssueIdentity 旧字段\n if (raw.issueId !== undefined || raw.issueIid !== undefined || raw.issueTitle !== undefined) {\n delete raw.issueId;\n delete raw.issueIid;\n delete raw.issueTitle;\n migrated++;\n }\n }\n if (migrated > 0) {\n this.save();\n logger.info('Migrated tracker records', { migrated });\n }\n }\n\n private lifecycleFor(record: IssueRecord): ActionLifecycleManager {\n if (record.pipelineMode) {\n const lm = this.lifecycleManagers.get(record.pipelineMode);\n if (lm) return lm;\n }\n // Fallback: 'plan-mode' or first registered manager\n return this.lifecycleManagers.get('plan-mode') ?? this.lifecycleManagers.values().next().value!;\n }\n\n private key(issueIid: number): string {\n return String(issueIid);\n }\n\n get(issueIid: number): IssueRecord | undefined {\n return this.getByKey(this.key(issueIid));\n }\n\n create(record: Omit<IssueRecord, 'createdAt' | 'updatedAt' | 'attempts'>): IssueRecord {\n const now = new Date().toISOString();\n const full: IssueRecord = {\n ...record,\n attempts: 0,\n createdAt: now,\n updatedAt: now,\n };\n this.setRecord(this.key(getIid(full)), full);\n this.save();\n logger.info('Issue tracked', { issueIid: getIid(full), state: record.state });\n eventBus.emitTyped('issue:created', full);\n return full;\n }\n\n updateState(issueIid: number, state: IssueState, extra?: Partial<IssueRecord>): void {\n const record = this.collection[this.key(issueIid)];\n if (!record) {\n throw new IssueNotFoundError(issueIid);\n }\n record.state = state;\n record.updatedAt = new Date().toISOString();\n if (state === IssueState.Completed) {\n record.lastError = undefined;\n record.failedAtState = undefined;\n }\n if (extra) {\n Object.assign(record, extra);\n }\n this.save();\n logger.info('Issue state updated', { issueIid, state });\n eventBus.emitTyped('issue:stateChanged', { issueIid, state, record });\n }\n\n markFailed(issueIid: number, error: string, failedAtState: IssueState): void {\n const record = this.collection[this.key(issueIid)];\n if (!record) return;\n record.state = IssueState.Failed;\n record.lastError = error;\n record.failedAtState = failedAtState;\n record.attempts += 1;\n record.updatedAt = new Date().toISOString();\n this.save();\n logger.warn('Issue marked as failed', { issueIid, error, failedAtState, attempts: record.attempts });\n eventBus.emitTyped('issue:failed', { issueIid, error, failedAtState, record });\n }\n\n isProcessing(issueIid: number): boolean {\n const record = this.get(issueIid);\n if (!record) return false;\n return !this.lifecycleFor(record).isTerminal(record.state);\n }\n\n isCompleted(issueIid: number): boolean {\n const record = this.get(issueIid);\n return record?.state === IssueState.Completed;\n }\n\n canRetry(issueIid: number, maxRetries: number): boolean {\n const record = this.get(issueIid);\n if (!record || record.state !== IssueState.Failed) return false;\n return record.attempts < maxRetries;\n }\n\n getRetryState(issueIid: number): IssueState | undefined {\n const record = this.get(issueIid);\n return record?.failedAtState;\n }\n\n isStalled(issueIid: number, thresholdMs: number = 5 * 60 * 1000): boolean {\n const record = this.get(issueIid);\n if (!record) return false;\n if (this.lifecycleFor(record).isBlocked(record.state)) return false;\n if (!this.isProcessing(issueIid)) return false;\n const elapsed = Date.now() - new Date(record.updatedAt).getTime();\n return elapsed > thresholdMs;\n }\n\n getDrivableIssues(maxRetries: number, stalledThresholdMs?: number): IssueRecord[] {\n return this.getAllRecords().filter((record) => {\n const lm = this.lifecycleFor(record);\n if (lm.isDrivable(record.state, record.attempts, maxRetries)) return true;\n if (this.isStalled(getIid(record), stalledThresholdMs)) return true;\n return false;\n });\n }\n\n getAllActive(): IssueRecord[] {\n return this.getAllRecords().filter(\n (r) => !this.lifecycleFor(r).isTerminal(r.state),\n );\n }\n\n getAll(): IssueRecord[] {\n return this.getAllRecords();\n }\n\n startSkipped(issueIid: number): boolean {\n const record = this.collection[this.key(issueIid)];\n if (!record || record.state !== IssueState.Skipped) return false;\n record.state = IssueState.Pending;\n record.updatedAt = new Date().toISOString();\n this.save();\n logger.info('Skipped issue started', { issueIid });\n eventBus.emitTyped('issue:stateChanged', { issueIid, state: IssueState.Pending, record });\n return true;\n }\n\n resetFull(issueIid: number): boolean {\n const record = this.collection[this.key(issueIid)];\n if (!record) return false;\n record.state = IssueState.Pending;\n record.attempts = 0;\n record.failedAtState = undefined;\n record.lastError = undefined;\n record.updatedAt = new Date().toISOString();\n this.save();\n logger.info('Issue fully reset', { issueIid });\n eventBus.emitTyped('issue:restarted', { issueIid, record });\n return true;\n }\n\n resetToPhase(issueIid: number, phase: string, def: PipelineDef): boolean {\n const record = this.collection[this.key(issueIid)];\n if (!record) return false;\n // Use a lifecycle manager matching the provided def, not the record's pipeline mode,\n // since the caller explicitly specifies which pipeline definition to use.\n const lm = this.lifecycleManagers.get(def.mode) ?? this.lifecycleFor(record);\n const targetState = lm.getPhasePreState(phase);\n if (!targetState) return false;\n record.state = targetState;\n // When resetting to a generic phase state, also set currentPhase\n if (targetState === IssueState.PhaseRunning || targetState === IssueState.PhaseDone\n || targetState === IssueState.PhaseWaiting || targetState === IssueState.PhaseApproved) {\n // The phase we're resetting to is the one *before* the given phase (its preState).\n // But since preState is BranchCreated for idx 0 or prev phase's doneState,\n // we need to find the actual phase name that this preState corresponds to.\n // For PhaseDone preState, the currentPhase should be the prev phase name.\n const phases = def.phases;\n const idx = phases.findIndex(p => p.name === phase);\n if (idx > 0) {\n record.currentPhase = phases[idx - 1].name;\n }\n }\n record.failedAtState = undefined;\n record.lastError = undefined;\n record.updatedAt = new Date().toISOString();\n this.save();\n logger.info('Issue reset to phase', { issueIid, phase, state: targetState });\n eventBus.emitTyped('issue:retryFromPhase', { issueIid, phase, record });\n return true;\n }\n\n resetForRetry(issueIid: number): boolean {\n const record = this.collection[this.key(issueIid)];\n if (!record || record.state !== IssueState.Failed) return false;\n\n const restoreState = record.failedAtState ?? IssueState.Pending;\n record.state = restoreState;\n record.lastError = undefined;\n record.updatedAt = new Date().toISOString();\n this.save();\n logger.info('Issue reset for retry', { issueIid, restoreState });\n eventBus.emitTyped('issue:resetForRetry', { issueIid, restoreState, record });\n return true;\n }\n\n delete(issueIid: number): boolean {\n const key = this.key(issueIid);\n const record = this.collection[key];\n if (!record) return false;\n delete this.collection[key];\n this.save();\n logger.info('Issue deleted from tracker', { issueIid });\n eventBus.emitTyped('issue:deleted', { issueIid, record });\n return true;\n }\n\n recoverInterruptedIssues(): number {\n let count = 0;\n for (const record of this.getAllRecords()) {\n const lm = this.lifecycleFor(record);\n if (lm.isInProgress(record.state)) {\n const iid = getIid(record);\n logger.warn('Recovering interrupted issue', {\n issueIid: iid,\n state: record.state,\n });\n record.failedAtState = record.state;\n record.state = IssueState.Failed;\n record.lastError = 'Interrupted by service restart';\n record.attempts += 1;\n record.updatedAt = new Date().toISOString();\n count++;\n eventBus.emitTyped('issue:failed', {\n issueIid: iid,\n error: 'Interrupted by service restart',\n failedAtState: record.failedAtState,\n record,\n });\n }\n }\n if (count > 0) {\n this.save();\n logger.info('Recovered interrupted issues', { count });\n }\n return count;\n }\n\n /** 将所有 IssueRecord 投影为 ExecutableTask[] */\n toExecutableTasks(): ExecutableTask[] {\n return this.getAllRecords().map((record) => {\n const lm = this.lifecycleFor(record);\n return issueToExecutableTask(record, lm);\n });\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { ProgressData, PhaseProgress } from '../tracker/IssueState.js';\nimport type { PipelineDef } from '../pipeline/PipelineDefinition.js';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('PlanPersistence');\n\nconst PLAN_DIR = '.claude-plan';\n\nexport interface ReviewRound {\n round: number;\n feedback: string;\n timestamp: string;\n}\n\nexport class PlanPersistence {\n private workDir: string;\n private issueIid: number;\n\n constructor(workDir: string, issueIid: number) {\n this.workDir = workDir;\n this.issueIid = issueIid;\n }\n\n get baseDir(): string {\n return this.workDir;\n }\n\n private get planDir(): string {\n return path.join(this.workDir, PLAN_DIR, `issue-${this.issueIid}`);\n }\n\n ensureDir(): void {\n if (!fs.existsSync(this.planDir)) {\n fs.mkdirSync(this.planDir, { recursive: true });\n }\n }\n\n writeIssueMeta(meta: { id: number; iid: number; title: string; labels: string[]; state: string }): void {\n this.ensureDir();\n const filePath = path.join(this.planDir, 'issue-meta.json');\n fs.writeFileSync(filePath, JSON.stringify(meta, null, 2), 'utf-8');\n logger.info('Issue meta written');\n }\n\n writeProgress(data: ProgressData): void {\n this.ensureDir();\n const filePath = path.join(this.planDir, 'progress.json');\n fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');\n logger.debug('Progress written', { currentPhase: data.currentPhase });\n }\n\n readProgress(): ProgressData | null {\n const filePath = path.join(this.planDir, 'progress.json');\n if (!fs.existsSync(filePath)) return null;\n try {\n return JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n } catch {\n return null;\n }\n }\n\n writeAnalysis(content: string): void {\n this.ensureDir();\n fs.writeFileSync(path.join(this.planDir, '01-analysis.md'), content, 'utf-8');\n logger.info('Analysis document written');\n }\n\n writeDesign(content: string): void {\n this.ensureDir();\n fs.writeFileSync(path.join(this.planDir, '02-design.md'), content, 'utf-8');\n logger.info('Design document written');\n }\n\n writeTodolist(content: string): void {\n this.ensureDir();\n fs.writeFileSync(path.join(this.planDir, '03-todolist.md'), content, 'utf-8');\n logger.info('Todolist written');\n }\n\n writeVerifyReport(content: string, filename = '04-verify-report.md'): void {\n this.ensureDir();\n fs.writeFileSync(path.join(this.planDir, filename), content, 'utf-8');\n logger.info('Verify report written', { filename });\n }\n\n getAllPlanFiles(): string[] {\n if (!fs.existsSync(this.planDir)) return [];\n return fs.readdirSync(this.planDir).map((f) => path.join(PLAN_DIR, `issue-${this.issueIid}`, f));\n }\n\n createInitialProgress(displayId: number, title: string, branchName: string, def?: PipelineDef): ProgressData {\n const pending: PhaseProgress = { status: 'pending' };\n if (def) {\n const phases: Record<string, PhaseProgress> = {};\n for (const spec of def.phases) {\n phases[spec.name] = { ...pending };\n }\n return {\n displayId,\n title,\n branchName,\n pipelineMode: def.mode,\n currentPhase: def.phases[0].name,\n phases,\n };\n }\n return {\n displayId,\n title,\n branchName,\n currentPhase: 'analysis',\n phases: {\n analysis: { ...pending },\n design: { ...pending },\n implement: { ...pending },\n verify: { ...pending },\n },\n };\n }\n\n writePlan(content: string): void {\n this.ensureDir();\n fs.writeFileSync(path.join(this.planDir, '01-plan.md'), content, 'utf-8');\n logger.info('Plan document written');\n }\n\n writeReviewFeedback(content: string): void {\n this.ensureDir();\n const history = this.readReviewHistory();\n const round: ReviewRound = {\n round: history.length + 1,\n feedback: content,\n timestamp: new Date().toISOString(),\n };\n history.push(round);\n fs.writeFileSync(\n path.join(this.planDir, 'review-history.json'),\n JSON.stringify(history, null, 2),\n 'utf-8',\n );\n fs.writeFileSync(\n path.join(this.planDir, 'review-feedback.md'),\n PlanPersistence.renderReviewHistoryMarkdown(history),\n 'utf-8',\n );\n logger.info('Review feedback appended', { round: round.round });\n }\n\n readReviewFeedback(): string | null {\n const filePath = path.join(this.planDir, 'review-feedback.md');\n if (!fs.existsSync(filePath)) return null;\n try {\n return fs.readFileSync(filePath, 'utf-8');\n } catch {\n return null;\n }\n }\n\n readReviewHistory(): ReviewRound[] {\n const filePath = path.join(this.planDir, 'review-history.json');\n if (!fs.existsSync(filePath)) return [];\n try {\n const data = JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n return Array.isArray(data) ? data : [];\n } catch {\n return [];\n }\n }\n\n static renderReviewHistoryMarkdown(history: ReviewRound[]): string {\n if (history.length === 0) return '';\n const lines = ['# 审核反馈历史', ''];\n for (const r of history) {\n lines.push(`## 第 ${r.round} 轮审核反馈`);\n lines.push(`> 时间: ${r.timestamp}`);\n lines.push('');\n lines.push(r.feedback);\n lines.push('');\n }\n return lines.join('\\n');\n }\n\n updatePhaseProgress(\n phaseName: string,\n status: 'in_progress' | 'completed' | 'failed',\n error?: string\n ): void {\n const progress = this.readProgress();\n if (!progress) return;\n\n const now = new Date().toISOString();\n if (!progress.phases[phaseName]) {\n progress.phases[phaseName] = { status: 'pending' };\n }\n const phase = progress.phases[phaseName];\n\n phase.status = status;\n if (status === 'in_progress') {\n phase.startedAt = now;\n progress.currentPhase = phaseName;\n } else if (status === 'completed') {\n phase.completedAt = now;\n } else if (status === 'failed') {\n phase.error = error;\n }\n\n this.writeProgress(progress);\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport type { AIRunner, RunResult } from '../ai-runner/index.js';\nimport { GitOperations } from '../git/GitOperations.js';\nimport { PlanPersistence } from '../persistence/PlanPersistence.js';\nimport { AIExecutionError } from '../errors/index.js';\nimport { IssueState } from '../tracker/IssueState.js';\nimport { ActionLifecycleManager } from '../lifecycle/ActionLifecycleManager.js';\nimport { issueProgressComment } from '../prompts/templates.js';\nimport { RuleResolver } from '../rules/index.js';\nimport { getProjectKnowledge } from '../knowledge/index.js';\nimport { eventBus } from '../events/EventBus.js';\nimport { Config } from '../config.js';\nimport {\n truncateToSummary,\n buildNoteSyncComment,\n} from '../notesync/NoteSyncSettings.js';\nimport type { PortPair } from '../deploy/PortAllocator.js';\nimport type { DemandSpec } from '../demand/DemandSpec.js';\nimport { logger as rootLogger, Logger } from '../logger.js';\nimport { t } from '../i18n/index.js';\n\n/** verify-fix loop 的修复上下文 — 当验证失败回退到 build 阶段时注入 */\nexport interface FixContext {\n /** 当前修复迭代轮次(1-based) */\n iteration: number;\n /** 上一轮验证中未通过的检查项描述 */\n verifyFailures: string[];\n /** 上一轮验证报告原文(截断) */\n rawReport: string;\n}\n\nexport interface PhaseContext {\n /** 需求规格(知识域) */\n demand: DemandSpec;\n /** 执行上下文(操作域) */\n branchName: string;\n pipelineMode?: string;\n ports?: PortPair;\n /** verify-fix loop 修复上下文(仅在修复迭代中存在) */\n fixContext?: FixContext;\n}\n\n/** 阶段生命周期钩子 — 由编排器注入,阶段不直接依赖 tracker/gongfeng */\nexport interface PhaseLifecycleHooks {\n onPhaseStart(phaseName: string): Promise<void>;\n onPhaseDone(phaseName: string): Promise<void>;\n onPhaseFailed(phaseName: string, error: string): Promise<void>;\n onComment(message: string): Promise<void>;\n isNoteSyncEnabled(): boolean;\n isE2eEnabled(): boolean;\n}\n\nexport abstract class BasePhase {\n private static readonly MIN_ARTIFACT_BYTES = 50;\n\n protected aiRunner: AIRunner;\n protected git: GitOperations;\n protected plan: PlanPersistence;\n protected config: Config;\n protected logger: Logger;\n private lifecycle: ActionLifecycleManager;\n protected hooks: PhaseLifecycleHooks;\n\n abstract readonly phaseName: string;\n\n get startState(): IssueState {\n const states = this.lifecycle.getPhaseStates(this.phaseName);\n if (!states) throw new Error(`Phase \"${this.phaseName}\" not found in lifecycle manager`);\n return states.startState;\n }\n\n get doneState(): IssueState {\n const states = this.lifecycle.getPhaseStates(this.phaseName);\n if (!states) throw new Error(`Phase \"${this.phaseName}\" not found in lifecycle manager`);\n return states.doneState;\n }\n\n constructor(\n aiRunner: AIRunner,\n git: GitOperations,\n plan: PlanPersistence,\n config: Config,\n lifecycle: ActionLifecycleManager,\n hooks: PhaseLifecycleHooks,\n ) {\n this.aiRunner = aiRunner;\n this.git = git;\n this.plan = plan;\n this.config = config;\n this.lifecycle = lifecycle;\n this.hooks = hooks;\n this.logger = rootLogger.child(this.constructor.name);\n }\n\n protected abstract buildPrompt(ctx: PhaseContext): string;\n\n protected getRunMode(): 'plan' | 'agent' | undefined {\n return undefined;\n }\n\n protected getResultFiles(_ctx?: PhaseContext): Array<{ filename: string; label: string }> {\n return [];\n }\n\n async execute(ctx: PhaseContext): Promise<RunResult> {\n const displayId = Number(ctx.demand.sourceRef.displayId);\n this.logger.info(`Phase ${this.phaseName} starting`, { issueIid: displayId });\n\n // Update tracker state via hooks\n await this.notifyPhaseStart();\n this.plan.updatePhaseProgress(this.phaseName, 'in_progress');\n\n // Comment on issue\n await this.notifyComment(\n issueProgressComment(this.phaseName, 'in_progress'),\n );\n\n const phaseLabel = t(`phase.${this.phaseName}`) || this.phaseName;\n eventBus.emitTyped('agent:output', {\n issueIid: displayId,\n phase: this.phaseName,\n event: {\n type: 'system',\n content: t('basePhase.aiStarting', { label: phaseLabel }),\n timestamp: new Date().toISOString(),\n },\n });\n\n // Build prompt and inject matched MDC rules\n const basePrompt = this.buildPrompt(ctx);\n const matchedRulesText = await this.resolveRules(ctx);\n const prompt = matchedRulesText\n ? `${basePrompt}\\n\\n${t('basePhase.rulesSection', { rules: matchedRulesText })}`\n : basePrompt;\n\n const result = await this.aiRunner.run({\n prompt,\n workDir: this.plan.baseDir,\n timeoutMs: this.config.ai.phaseTimeoutMs,\n idleTimeoutMs: this.config.ai.idleTimeoutMs,\n mode: this.getRunMode(),\n onStreamEvent: (event) => {\n eventBus.emitTyped('agent:output', {\n issueIid: displayId,\n phase: this.phaseName,\n event,\n });\n },\n });\n\n if (!result.success) {\n // 优先使用 errorMessage(真正的失败原因),降级到 output\n const failReason = (result.errorMessage || result.output).slice(0, 500);\n const shortReason = (result.errorMessage || result.output).slice(0, 200);\n\n this.plan.updatePhaseProgress(this.phaseName, 'failed', failReason);\n await this.notifyPhaseFailed(failReason);\n\n await this.notifyComment(\n issueProgressComment(this.phaseName, 'failed', t('basePhase.error', { message: shortReason })),\n );\n\n throw new AIExecutionError(this.phaseName, `Phase ${this.phaseName} failed: ${shortReason}`, {\n output: result.output,\n exitCode: result.exitCode,\n });\n }\n\n await this.validatePhaseOutput(ctx, displayId);\n\n await this.notifyPhaseDone();\n this.plan.updatePhaseProgress(this.phaseName, 'completed');\n\n await this.commitPlanFiles(ctx, displayId);\n\n await this.syncResultToIssue(ctx, displayId);\n\n this.logger.info(`Phase ${this.phaseName} completed`, { issueIid: displayId });\n return result;\n }\n\n // ── Hook dispatch methods ──\n\n private async notifyPhaseStart(): Promise<void> {\n await this.hooks.onPhaseStart(this.phaseName);\n }\n\n private async notifyPhaseDone(): Promise<void> {\n await this.hooks.onPhaseDone(this.phaseName);\n }\n\n private async notifyPhaseFailed(error: string): Promise<void> {\n await this.hooks.onPhaseFailed(this.phaseName, error);\n }\n\n private async notifyComment(message: string): Promise<void> {\n try {\n await this.hooks.onComment(message);\n } catch (err) {\n this.logger.warn('Hook onComment failed', { error: (err as Error).message });\n }\n }\n\n protected async resolveRules(ctx: PhaseContext): Promise<string | null> {\n try {\n const rulesDir = path.join(this.plan.baseDir, '.cursor', 'rules');\n const knowledge = getProjectKnowledge();\n const resolver = new RuleResolver(knowledge?.ruleTriggers);\n await resolver.loadRules(rulesDir);\n const context = `${ctx.demand.title} ${ctx.demand.description} ${ctx.demand.supplement ? JSON.stringify(ctx.demand.supplement) : ''}`;\n const matched = resolver.matchRules(context);\n if (matched.length > 0) {\n this.logger.info(`Matched ${matched.length} MDC rules`, {\n rules: matched.map(r => r.filename),\n });\n return resolver.formatForPrompt(matched);\n }\n } catch (err) {\n this.logger.warn('Failed to resolve MDC rules', { error: (err as Error).message });\n }\n return null;\n }\n\n private async syncResultToIssue(ctx: PhaseContext, displayId: number): Promise<void> {\n try {\n const enabled = this.hooks.isNoteSyncEnabled();\n const resultFiles = this.getResultFiles(ctx);\n\n if (!enabled || resultFiles.length === 0) {\n await this.notifyComment(\n issueProgressComment(this.phaseName, 'completed'),\n );\n return;\n }\n\n const baseUrl = this.config.issueNoteSync.webBaseUrl.replace(/\\/$/, '');\n const phaseLabel = t(`phase.${this.phaseName}`) || this.phaseName;\n const dashboardUrl = `${baseUrl}/?issue=${displayId}`;\n\n for (const file of resultFiles) {\n const content = this.readResultFile(displayId, file.filename);\n if (!content) continue;\n\n const summary = truncateToSummary(content);\n const docUrl = `${baseUrl}/doc/${displayId}/${file.filename}`;\n const comment = buildNoteSyncComment(\n this.phaseName, file.label || phaseLabel, docUrl, dashboardUrl, summary,\n );\n\n await this.notifyComment(comment);\n this.logger.info('Result synced to issue', { issueIid: displayId, file: file.filename });\n }\n } catch (err) {\n this.logger.warn('Failed to sync result to issue', { error: (err as Error).message });\n await this.notifyComment(\n issueProgressComment(this.phaseName, 'completed'),\n );\n }\n }\n\n private readResultFile(issueIid: number, filename: string): string | null {\n const planDir = path.join(this.plan.baseDir, '.claude-plan', `issue-${issueIid}`);\n const filePath = path.join(planDir, filename);\n if (!fs.existsSync(filePath)) return null;\n try {\n return fs.readFileSync(filePath, 'utf-8');\n } catch {\n return null;\n }\n }\n\n protected async validatePhaseOutput(ctx: PhaseContext, displayId: number): Promise<void> {\n const resultFiles = this.getResultFiles(ctx);\n if (resultFiles.length === 0) return;\n\n const planDir = path.join(this.plan.baseDir, '.claude-plan', `issue-${displayId}`);\n const missing: string[] = [];\n\n for (const file of resultFiles) {\n const filePath = path.join(planDir, file.filename);\n if (!fs.existsSync(filePath)) {\n missing.push(file.filename);\n continue;\n }\n const stat = fs.statSync(filePath);\n if (stat.size < BasePhase.MIN_ARTIFACT_BYTES) {\n missing.push(`${file.filename} (${stat.size} bytes, 内容不足)`);\n }\n }\n\n if (missing.length > 0) {\n const msg = `AI 进程成功退出但未生成预期产物: ${missing.join(', ')}`;\n this.logger.error(msg, { phase: this.phaseName, displayId });\n throw new AIExecutionError(this.phaseName, msg, { output: '', exitCode: 0 });\n }\n }\n\n private async commitPlanFiles(ctx: PhaseContext, displayId: number): Promise<void> {\n if (await this.git.hasChanges()) {\n await this.git.add(['.']);\n await this.git.commit(`chore(auto): ${this.phaseName} phase completed for issue #${displayId}`);\n await this.git.push(ctx.branchName);\n }\n }\n}\n","import { readdir, readFile } from 'node:fs/promises';\nimport path from 'node:path';\nimport type { RuleTriggerConfig } from '../knowledge/ProjectKnowledge.js';\n\nexport interface MdcRule {\n filename: string;\n description: string;\n alwaysApply: boolean;\n content: string;\n}\n\nfunction parseFrontmatter(raw: string): { description: string; alwaysApply: boolean; content: string } {\n const fmRegex = /^---\\s*\\n([\\s\\S]*?)\\n---\\s*\\n/;\n const match = raw.match(fmRegex);\n if (!match) {\n return { description: '', alwaysApply: false, content: raw.trim() };\n }\n\n const yamlBlock = match[1];\n const content = raw.slice(match[0].length).trim();\n\n let description = '';\n const descMatch = yamlBlock.match(/description:\\s*(.+)/);\n if (descMatch) {\n description = descMatch[1].trim();\n }\n\n let alwaysApply = false;\n const applyMatch = yamlBlock.match(/alwaysApply:\\s*(true|false)/i);\n if (applyMatch) {\n alwaysApply = applyMatch[1].toLowerCase() === 'true';\n }\n\n return { description, alwaysApply, content };\n}\n\nexport class RuleResolver {\n private rules: MdcRule[] = [];\n private triggers: RuleTriggerConfig[] | undefined;\n\n constructor(ruleTriggers?: RuleTriggerConfig[]) {\n this.triggers = ruleTriggers;\n }\n\n public async loadRules(rulesDir: string): Promise<void> {\n this.rules = [];\n let files: string[];\n try {\n files = await readdir(rulesDir);\n } catch {\n return;\n }\n\n const mdcFiles = files.filter(f => f.endsWith('.mdc'));\n\n const loadPromises = mdcFiles.map(async (filename) => {\n try {\n const raw = await readFile(path.join(rulesDir, filename), 'utf-8');\n const { description, alwaysApply, content } = parseFrontmatter(raw);\n if (content) {\n this.rules.push({ filename, description, alwaysApply, content });\n }\n } catch {\n // skip unreadable files\n }\n });\n\n await Promise.all(loadPromises);\n }\n\n public getRules(): MdcRule[] {\n return this.rules;\n }\n\n public matchRules(text: string): MdcRule[] {\n const lowerText = text.toLowerCase();\n const matched = new Map<string, MdcRule>();\n\n // Always include alwaysApply rules\n for (const rule of this.rules) {\n if (rule.alwaysApply) {\n matched.set(rule.filename, rule);\n }\n }\n\n if (this.triggers && this.triggers.length > 0) {\n // Use configured triggers for keyword matching\n for (const trigger of this.triggers) {\n if (matched.has(trigger.filename)) continue;\n const isTriggered = trigger.keywords.some(kw => lowerText.includes(kw.toLowerCase()));\n if (!isTriggered) continue;\n\n const rule = this.rules.find(r => r.filename === trigger.filename);\n if (rule) {\n matched.set(rule.filename, rule);\n }\n }\n } else {\n // Fallback: match based on frontmatter description words\n for (const rule of this.rules) {\n if (matched.has(rule.filename)) continue;\n if (!rule.description) continue;\n\n const descWords = rule.description\n .split(/[\\s,,;;、/|]+/)\n .filter(w => w.length >= 2);\n const isMatched = descWords.some(word => lowerText.includes(word.toLowerCase()));\n if (isMatched) {\n matched.set(rule.filename, rule);\n }\n }\n }\n\n return Array.from(matched.values());\n }\n\n public formatForPrompt(rules: MdcRule[]): string {\n if (rules.length === 0) return '';\n\n return rules.map(rule => {\n const header = rule.description\n ? `### ${rule.description} (${rule.filename})`\n : `### ${rule.filename}`;\n return `${header}\\n\\n${rule.content}`;\n }).join('\\n\\n---\\n\\n');\n }\n}\n","import type { Config } from '../config.js';\nimport type { IssueTracker } from '../tracker/IssueTracker.js';\nimport { t } from '../i18n/index.js';\n\nlet noteSyncOverride: boolean | undefined;\n\nexport function getNoteSyncEnabled(cfg: Config): boolean {\n return noteSyncOverride ?? cfg.issueNoteSync.enabled;\n}\n\nexport function setNoteSyncOverride(value: boolean | undefined): void {\n noteSyncOverride = value;\n}\n\nexport function isNoteSyncEnabledForIssue(\n issueIid: number,\n tracker: IssueTracker,\n cfg: Config,\n): boolean {\n const record = tracker.get(issueIid);\n if (record?.issueNoteSyncEnabled !== undefined) return record.issueNoteSyncEnabled;\n return getNoteSyncEnabled(cfg);\n}\n\nconst SUMMARY_MAX_LENGTH = 500;\n\nexport function truncateToSummary(content: string): string {\n if (content.length <= SUMMARY_MAX_LENGTH) return content;\n const cut = content.slice(0, SUMMARY_MAX_LENGTH);\n const lastNewline = cut.lastIndexOf('\\n\\n');\n const boundary = lastNewline > SUMMARY_MAX_LENGTH * 0.3 ? lastNewline : cut.lastIndexOf('\\n');\n const summary = boundary > SUMMARY_MAX_LENGTH * 0.3 ? cut.slice(0, boundary) : cut;\n return summary + '\\n\\n...';\n}\n\nexport interface ResultFileSpec {\n filename: string;\n label: string;\n}\n\nexport function buildNoteSyncComment(\n phaseName: string,\n phaseLabel: string,\n docUrl: string,\n dashboardUrl: string,\n summary: string,\n): string {\n const emoji: Record<string, string> = {\n analysis: '🔍', design: '📐', implement: '💻', verify: '✅',\n plan: '📋', review: '👀', build: '🔨',\n };\n const icon = emoji[phaseName] || '📋';\n return [\n t('notesync.phaseCompleted', { icon, label: phaseLabel }),\n '',\n summary,\n '',\n '---',\n t('notesync.viewDoc', { label: phaseLabel, url: docUrl }),\n t('notesync.viewDashboard', { url: dashboardUrl }),\n ].join('\\n');\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { BasePhase, PhaseContext } from './BasePhase.js';\nimport { verifyPrompt, planModeVerifyPrompt, e2eVerifyPromptSuffix, demandToPromptContext } from '../prompts/templates.js';\nimport { getLocalIP } from '../utils/network.js';\nimport { VerifyReportParser } from '../verify/index.js';\nimport type { RunResult } from '../ai-runner/index.js';\nimport type { VerifyReportResult } from '../verify/index.js';\n\nfunction getDefaultHost(): string {\n return getLocalIP();\n}\n\nexport interface VerifyRunResult extends RunResult {\n verifyReport?: VerifyReportResult;\n}\n\nexport class VerifyPhase extends BasePhase {\n readonly phaseName = 'verify' as const;\n private readonly reportParser = new VerifyReportParser();\n\n protected getResultFiles(ctx?: PhaseContext) {\n const filename = ctx?.pipelineMode === 'plan-mode' ? '02-verify-report.md' : '04-verify-report.md';\n return [{ filename, label: '验证报告' }];\n }\n\n async execute(ctx: PhaseContext): Promise<VerifyRunResult> {\n const result = await super.execute(ctx);\n\n // AI 进程成功退出后,读取并解析验证报告\n if (result.success) {\n const report = this.readVerifyReport(ctx);\n if (report) {\n const parsed = this.reportParser.parse(report);\n\n // 如果启用了 todolist 检查,从 plan 文件补充统计\n if (this.config.verifyFixLoop.todolistCheckEnabled && !parsed.todolistStats) {\n const planContent = this.readPlanFile(ctx);\n if (planContent) {\n const todoStats = this.reportParser.parseTodolistFromPlan(planContent);\n if (todoStats.total > 0) {\n parsed.todolistStats = todoStats;\n parsed.todolistComplete = todoStats.completed === todoStats.total;\n if (!parsed.todolistComplete) {\n parsed.failureReasons.push(\n `Todolist 未全部完成(${todoStats.completed}/${todoStats.total})`,\n );\n parsed.passed = false;\n }\n }\n }\n }\n\n this.logger.info('Verify report parsed', {\n passed: parsed.passed,\n lintPassed: parsed.lintPassed,\n buildPassed: parsed.buildPassed,\n testPassed: parsed.testPassed,\n todolistComplete: parsed.todolistComplete,\n todolistStats: parsed.todolistStats,\n failureCount: parsed.failureReasons.length,\n });\n\n return { ...result, verifyReport: parsed };\n }\n }\n\n return result;\n }\n\n protected buildPrompt(ctx: PhaseContext): string {\n const pc = demandToPromptContext(ctx.demand);\n const promptCtx = {\n issueTitle: pc.title,\n issueDescription: pc.description,\n issueIid: Number(pc.displayId),\n };\n const base = ctx.pipelineMode === 'plan-mode'\n ? planModeVerifyPrompt(promptCtx)\n : verifyPrompt(promptCtx);\n\n if (!this.hooks.isE2eEnabled()) {\n return base;\n }\n\n const e2ePorts = ctx.ports\n ? {\n backendPort: ctx.ports.backendPort,\n frontendPort: ctx.ports.frontendPort,\n host: this.config.preview.host || getDefaultHost(),\n }\n : undefined;\n\n return base + e2eVerifyPromptSuffix(promptCtx, e2ePorts);\n }\n\n private readVerifyReport(ctx: PhaseContext): string | null {\n const files = this.getResultFiles(ctx);\n if (files.length === 0) return null;\n\n const displayId = Number(ctx.demand.sourceRef.displayId);\n const planDir = path.join(this.plan.baseDir, '.claude-plan', `issue-${displayId}`);\n const filePath = path.join(planDir, files[0].filename);\n\n if (!fs.existsSync(filePath)) return null;\n try {\n return fs.readFileSync(filePath, 'utf-8');\n } catch {\n return null;\n }\n }\n\n private readPlanFile(ctx: PhaseContext): string | null {\n const displayId = Number(ctx.demand.sourceRef.displayId);\n const planDir = path.join(this.plan.baseDir, '.claude-plan', `issue-${displayId}`);\n const filePath = path.join(planDir, '01-plan.md');\n\n if (!fs.existsSync(filePath)) return null;\n try {\n return fs.readFileSync(filePath, 'utf-8');\n } catch {\n return null;\n }\n }\n}\n","/**\n * 解析验证阶段生成的报告,提取通过/失败状态和失败原因。\n *\n * 解析逻辑基于验证 prompt 要求 AI 输出的结构化格式,\n * 同时兼容中英文和多种常见写法。\n */\n\nexport interface TodolistStats {\n completed: number;\n total: number;\n}\n\nexport interface VerifyReportResult {\n /** 综合判定:所有检查项均通过 */\n passed: boolean;\n lintPassed: boolean;\n buildPassed: boolean;\n testPassed: boolean;\n todolistComplete: boolean;\n todolistStats?: TodolistStats;\n /** 未通过的检查项及其原因 */\n failureReasons: string[];\n /** 原始报告内容 */\n rawReport: string;\n}\n\n// -- 匹配模式 --\n\n// \"Lint 结果: 失败\" / \"**Lint 结果**: 失败\" / \"Lint Result: Failed\"\nconst LINT_FAIL_RE = /\\*{0,2}Lint\\s*(?:结果|Result)\\*{0,2}\\s*[::]\\s*(?:失败|failed|fail|未通过)/i;\nconst BUILD_FAIL_RE = /\\*{0,2}Build\\s*(?:结果|Result)\\*{0,2}\\s*[::]\\s*(?:失败|failed|fail|未通过)/i;\nconst TEST_FAIL_RE = /\\*{0,2}Test\\s*(?:结果|Result)\\*{0,2}\\s*[::]\\s*(?:失败|failed|fail|未通过)/i;\n\n// \"总结: 验证失败\" / \"**总结**: 验证失败\" / \"Summary: Verification Failed\"\nconst SUMMARY_FAIL_RE = /\\*{0,2}(?:总结|Summary)\\*{0,2}\\s*[::].*(?:验证失败|verification\\s+failed|failed|失败)/i;\n\n// \"Todolist 检查: 3/5 项完成\" 或 \"**Todolist 检查**: 3/5\" 或 \"Todolist: 3/5\"\nconst TODOLIST_STATS_RE = /\\*{0,2}(?:Todolist|Todo)\\s*(?:检查|check)?\\*{0,2}\\s*[::]\\s*(\\d+)\\s*[//]\\s*(\\d+)/i;\n\nexport class VerifyReportParser {\n /**\n * 解析验证报告内容。\n *\n * @param reportContent 验证报告的完整 Markdown 文本\n */\n parse(reportContent: string): VerifyReportResult {\n const lintPassed = !LINT_FAIL_RE.test(reportContent);\n const buildPassed = !BUILD_FAIL_RE.test(reportContent);\n const testPassed = !TEST_FAIL_RE.test(reportContent);\n\n const todolistStats = this.parseTodolistStats(reportContent);\n const todolistComplete = todolistStats\n ? todolistStats.total === 0 || todolistStats.completed === todolistStats.total\n : true; // 无统计数据时默认视为完成(不误判)\n\n const failureReasons: string[] = [];\n if (!lintPassed) failureReasons.push('Lint 检查失败');\n if (!buildPassed) failureReasons.push('Build 编译失败');\n if (!testPassed) failureReasons.push('测试未通过');\n if (!todolistComplete) {\n const statsText = todolistStats\n ? `(${todolistStats.completed}/${todolistStats.total})`\n : '';\n failureReasons.push(`Todolist 未全部完成${statsText}`);\n }\n\n // 如果上面各项都看似通过,但总结中明确写了\"验证失败\",依然判为失败\n const summaryFailed = SUMMARY_FAIL_RE.test(reportContent);\n if (failureReasons.length === 0 && summaryFailed) {\n failureReasons.push('验证报告总结判定为失败');\n }\n\n const passed = failureReasons.length === 0;\n\n return {\n passed,\n lintPassed,\n buildPassed,\n testPassed,\n todolistComplete,\n todolistStats: todolistStats ?? undefined,\n failureReasons,\n rawReport: reportContent,\n };\n }\n\n /**\n * 从 plan 文件中解析 Todolist 完成度。\n * 统计 `- [x]` (已完成) 和 `- [ ]` (未完成) 的数量。\n */\n parseTodolistFromPlan(planContent: string): TodolistStats {\n const completedRe = /^[ \\t]*-\\s+\\[x\\]/gim;\n const uncompletedRe = /^[ \\t]*-\\s+\\[\\s\\]/gm;\n\n const completedMatches = planContent.match(completedRe);\n const uncompletedMatches = planContent.match(uncompletedRe);\n\n const completed = completedMatches?.length ?? 0;\n const uncompleted = uncompletedMatches?.length ?? 0;\n\n return {\n completed,\n total: completed + uncompleted,\n };\n }\n\n /**\n * 从报告中提取 Todolist 统计数据。\n * 格式: \"Todolist 检查: X/Y 项完成\"\n */\n private parseTodolistStats(reportContent: string): TodolistStats | null {\n const match = reportContent.match(TODOLIST_STATS_RE);\n if (match) {\n return {\n completed: parseInt(match[1], 10),\n total: parseInt(match[2], 10),\n };\n }\n return null;\n }\n}\n","import { BasePhase, PhaseContext } from './BasePhase.js';\nimport { planPrompt, rePlanPrompt, demandToPromptContext } from '../prompts/templates.js';\nimport { getRunnerCapabilities } from '../ai-runner/index.js';\nimport { t } from '../i18n/index.js';\n\nexport class PlanPhase extends BasePhase {\n readonly phaseName = 'plan' as const;\n\n protected getResultFiles() {\n return [{ filename: '01-plan.md', label: '实施计划' }];\n }\n\n protected getRunMode(): 'plan' | 'agent' | undefined {\n return 'plan';\n }\n\n protected buildPrompt(ctx: PhaseContext): string {\n const pc = demandToPromptContext(ctx.demand);\n const history = this.plan.readReviewHistory();\n const promptCtx = {\n issueTitle: pc.title,\n issueDescription: pc.description,\n issueIid: Number(pc.displayId),\n supplementText: pc.supplementText || undefined,\n };\n\n let basePrompt: string;\n if (history.length > 0) {\n basePrompt = rePlanPrompt(promptCtx, history);\n } else {\n basePrompt = planPrompt(promptCtx);\n }\n\n // Prepend plan-mode fallback instructions for runners without native plan mode\n const caps = getRunnerCapabilities(this.config.ai.mode);\n if (!caps?.nativePlanMode) {\n basePrompt = `${t('prompt.planModeFallback')}\\n\\n${basePrompt}`;\n }\n\n return basePrompt;\n }\n}\n","import { BasePhase, PhaseContext } from './BasePhase.js';\nimport { buildPrompt, demandToPromptContext } from '../prompts/templates.js';\nimport { AIExecutionError } from '../errors/index.js';\nimport { t } from '../i18n/index.js';\n\nexport class BuildPhase extends BasePhase {\n readonly phaseName = 'build' as const;\n\n protected async validatePhaseOutput(_ctx: PhaseContext, _displayId: number): Promise<void> {\n if (!await this.git.hasChanges()) {\n const msg = 'AI 进程成功退出但未产生任何代码变更';\n this.logger.error(msg, { phase: this.phaseName });\n throw new AIExecutionError(this.phaseName, msg, { output: '', exitCode: 0 });\n }\n }\n\n protected buildPrompt(ctx: PhaseContext): string {\n const pc = demandToPromptContext(ctx.demand);\n const base = buildPrompt({\n issueTitle: pc.title,\n issueDescription: pc.description,\n issueIid: Number(pc.displayId),\n });\n\n if (ctx.fixContext) {\n return base + t('prompt.buildFixSuffix', {\n iteration: ctx.fixContext.iteration,\n failures: ctx.fixContext.verifyFailures.map((f, i) => `${i + 1}. ${f}`).join('\\n'),\n rawReport: ctx.fixContext.rawReport.slice(0, 2000),\n });\n }\n\n return base;\n }\n}\n","import type { AIRunner } from '../ai-runner/index.js';\nimport { GitOperations } from '../git/GitOperations.js';\nimport { PlanPersistence } from '../persistence/PlanPersistence.js';\nimport { Config } from '../config.js';\nimport { PhaseNotRegisteredError, UnregisteredPhasesError } from '../errors/index.js';\nimport { ActionLifecycleManager } from '../lifecycle/ActionLifecycleManager.js';\nimport { BasePhase, PhaseLifecycleHooks } from './BasePhase.js';\nimport { VerifyPhase } from './VerifyPhase.js';\nimport { PlanPhase } from './PlanPhase.js';\nimport { BuildPhase } from './BuildPhase.js';\n\ntype PhaseArgs = [AIRunner, GitOperations, PlanPersistence, Config, ActionLifecycleManager, PhaseLifecycleHooks];\nexport type PhaseConstructor = new (...args: PhaseArgs) => BasePhase;\n\n// ---------------------------------------------------------------------------\n// Phase Registry\n// ---------------------------------------------------------------------------\n\nconst PHASE_REGISTRY = new Map<string, PhaseConstructor>();\n\n/** 注册一个阶段构造器。重复注册同一 name 会覆盖。 */\nexport function registerPhase(name: string, ctor: PhaseConstructor): void {\n PHASE_REGISTRY.set(name, ctor);\n}\n\n/** 用于测试隔离:重置注册表并重新注册内置阶段 */\nexport function _resetPhaseRegistry(): void {\n PHASE_REGISTRY.clear();\n registerBuiltinPhases();\n}\n\n// ---------------------------------------------------------------------------\n// Self-register built-in phases\n// ---------------------------------------------------------------------------\n\nfunction registerBuiltinPhases(): void {\n PHASE_REGISTRY.set('plan', PlanPhase);\n PHASE_REGISTRY.set('build', BuildPhase);\n PHASE_REGISTRY.set('verify', VerifyPhase);\n}\n\nregisterBuiltinPhases();\n\n// ---------------------------------------------------------------------------\n// Factory / validation\n// ---------------------------------------------------------------------------\n\nexport function createPhase(name: string, ...args: PhaseArgs): BasePhase {\n const Ctor = PHASE_REGISTRY.get(name);\n if (!Ctor) {\n throw new PhaseNotRegisteredError(name, [...PHASE_REGISTRY.keys()]);\n }\n return new Ctor(...args);\n}\n\n/** 校验 PipelineDef 中的所有 AI phase 都已注册,应在启动时调用 */\nexport function validatePhaseRegistry(phaseNames: string[]): void {\n const missing = phaseNames.filter(name => !PHASE_REGISTRY.has(name));\n if (missing.length > 0) {\n throw new UnregisteredPhasesError(missing, [...PHASE_REGISTRY.keys()]);\n }\n}\n","import { IssueState } from '../tracker/IssueState.js';\nimport type { PipelineDef, PhaseSpec, PlanFileSpec } from '../pipeline/PipelineDefinition.js';\nimport type { ActionState, ActionStatus } from './ActionLifecycle.js';\nimport { t } from '../i18n/index.js';\n\n/**\n * ActionLifecycleManager — 查询层抽象。\n *\n * 从 PipelineDef 自动构建 IssueState ↔ ActionState 双向映射表,\n * 集中散布在 IssueTracker/PipelineOrchestrator/BasePhase 中的状态分类逻辑。\n *\n * 不改变持久化格式(tracker.json 中的状态字符串值完全保留)。\n */\nexport class ActionLifecycleManager {\n /** IssueState → ActionState */\n private readonly stateToAction: Map<IssueState, ActionState>;\n /** \"action:status\" → IssueState */\n private readonly actionToState: Map<string, IssueState>;\n /** phase name → { startState, doneState, approvedState? } */\n private readonly phaseStatesMap: Map<string, { startState: IssueState; doneState: IssueState; approvedState?: IssueState }>;\n /** Ordered phase indices by IssueState for determineResumePhaseIndex */\n private readonly def: PipelineDef;\n\n constructor(def: PipelineDef) {\n this.def = def;\n this.stateToAction = new Map();\n this.actionToState = new Map();\n this.phaseStatesMap = new Map();\n\n this.buildMappings(def);\n }\n\n private buildMappings(def: PipelineDef): void {\n // Fixed mappings\n this.addMapping(IssueState.Pending, 'init', 'idle');\n this.addMapping(IssueState.Skipped, 'init', 'skipped');\n this.addMapping(IssueState.BranchCreated, 'init', 'ready');\n this.addMapping(IssueState.Failed, 'init', 'failed');\n this.addMapping(IssueState.ResolvingConflict, 'conflict', 'running');\n\n // Phase-driven mappings\n for (const spec of def.phases) {\n this.phaseStatesMap.set(spec.name, {\n startState: spec.startState,\n doneState: spec.doneState,\n approvedState: spec.approvedState,\n });\n\n if (spec.kind === 'ai') {\n // For generic PhaseRunning/PhaseDone, don't add to stateToAction map\n // (since multiple phases share the same IssueState value).\n // Only add non-generic states.\n if (spec.startState !== IssueState.PhaseRunning) {\n this.addMapping(spec.startState, spec.name, 'running');\n }\n if (spec.doneState === IssueState.Completed) {\n this.addMapping(spec.doneState, spec.name, 'done');\n } else if (spec.doneState !== IssueState.PhaseDone) {\n this.addMapping(spec.doneState, spec.name, 'ready');\n }\n } else if (spec.kind === 'gate') {\n // For generic PhaseWaiting/PhaseApproved, don't add to stateToAction map\n // (since multiple gate phases could share the same IssueState value).\n if (spec.startState !== IssueState.PhaseWaiting) {\n this.addMapping(spec.startState, spec.name, 'waiting');\n }\n if (spec.approvedState && spec.approvedState !== IssueState.PhaseApproved) {\n this.addMapping(spec.approvedState, spec.name, 'ready');\n }\n }\n }\n }\n\n private addMapping(state: IssueState, action: string, status: ActionStatus): void {\n // Avoid overwriting — first mapping wins (e.g. Completed mapped by verify phase)\n if (!this.stateToAction.has(state)) {\n this.stateToAction.set(state, { action, status });\n }\n const key = `${action}:${status}`;\n if (!this.actionToState.has(key)) {\n this.actionToState.set(key, state);\n }\n }\n\n // ─── Query API ───\n\n /**\n * 将 IssueState 解析为语义化的 ActionState。\n *\n * 对于通用状态 PhaseRunning/PhaseDone,需额外传入 currentPhase 来区分具体阶段。\n */\n resolve(state: IssueState, currentPhase?: string): ActionState {\n // 通用阶段状态:用 currentPhase 作为 action 名\n if (state === IssueState.PhaseRunning && currentPhase) {\n return { action: currentPhase, status: 'running' };\n }\n if (state === IssueState.PhaseDone && currentPhase) {\n return { action: currentPhase, status: 'ready' };\n }\n if (state === IssueState.PhaseWaiting && currentPhase) {\n return { action: currentPhase, status: 'waiting' };\n }\n if (state === IssueState.PhaseApproved && currentPhase) {\n return { action: currentPhase, status: 'ready' };\n }\n\n const mapped = this.stateToAction.get(state);\n if (mapped) return mapped;\n // Fallback: unknown states (from another pipeline mode) treated as idle\n return { action: 'init', status: 'idle' };\n }\n\n /**\n * 将 action + status 反向映射为 IssueState。\n */\n toIssueState(action: string, status: ActionStatus): IssueState | undefined {\n return this.actionToState.get(`${action}:${status}`);\n }\n\n // ─── Classification predicates (替代 3 个 Set 常量 + getDrivableIssues) ───\n\n /**\n * 终态:done | failed | skipped\n */\n isTerminal(state: IssueState): boolean {\n const as = this.resolve(state);\n return as.status === 'done' || as.status === 'failed' || as.status === 'skipped';\n }\n\n /**\n * 进行中:running (包含通用 PhaseRunning)\n */\n isInProgress(state: IssueState): boolean {\n if (state === IssueState.PhaseRunning) return true;\n return this.resolve(state).status === 'running';\n }\n\n /**\n * 阻塞中:waiting\n */\n isBlocked(state: IssueState): boolean {\n if (state === IssueState.PhaseWaiting) return true;\n return this.resolve(state).status === 'waiting';\n }\n\n /**\n * 可驱动判断(集中化 getDrivableIssues 的过滤逻辑)。\n *\n * - idle → 可驱动 (Pending)\n * - ready → 可驱动 (BranchCreated, PhaseDone, PhaseApproved)\n * - failed && attempts < maxRetries → 可驱动\n * - waiting → 不可驱动 (PhaseWaiting)\n * - running → 不可驱动(stalled 由外部叠加)\n * - done/skipped → 不可驱动\n */\n isDrivable(state: IssueState, attempts: number, maxRetries: number): boolean {\n // PhaseDone is always drivable (triggers next phase)\n if (state === IssueState.PhaseDone) return true;\n // PhaseApproved is always drivable (gate approved, triggers next phase)\n if (state === IssueState.PhaseApproved) return true;\n // PhaseRunning is never drivable (something is executing)\n if (state === IssueState.PhaseRunning) return false;\n // PhaseWaiting is never drivable (waiting for external input)\n if (state === IssueState.PhaseWaiting) return false;\n const as = this.resolve(state);\n switch (as.status) {\n case 'idle':\n case 'ready':\n return true;\n case 'failed':\n return attempts < maxRetries;\n case 'waiting':\n case 'running':\n case 'done':\n case 'skipped':\n return false;\n }\n }\n\n // ─── Phase navigation (替代 determineStartIndex + getPhasePreState) ───\n\n /**\n * 确定从哪个阶段索引恢复执行(替代 PipelineOrchestrator.determineStartIndex)。\n *\n * 从后向前扫描 phases,匹配 currentState 或 failedAtState。\n * 支持通用状态 PhaseRunning/PhaseDone + currentPhase 的组合。\n */\n determineResumePhaseIndex(currentState: IssueState, failedAtState?: IssueState, currentPhase?: string): number {\n const target = failedAtState || currentState;\n const phases = this.def.phases;\n\n // 通用阶段状态:通过 currentPhase 名称匹配\n if ((target === IssueState.PhaseRunning || target === IssueState.PhaseDone) && currentPhase) {\n const idx = phases.findIndex(p => p.name === currentPhase);\n if (idx >= 0) {\n return target === IssueState.PhaseDone ? idx + 1 : idx;\n }\n }\n if ((target === IssueState.PhaseWaiting || target === IssueState.PhaseApproved) && currentPhase) {\n const idx = phases.findIndex(p => p.name === currentPhase);\n if (idx >= 0) {\n return target === IssueState.PhaseApproved ? idx + 1 : idx;\n }\n }\n\n for (let i = phases.length - 1; i >= 0; i--) {\n const spec = phases[i];\n\n if (spec.kind === 'gate' && spec.approvedState === target) {\n return i + 1;\n }\n\n if (spec.startState === target || spec.doneState === target) {\n return spec.doneState === target ? i + 1 : i;\n }\n }\n return 0;\n }\n\n /**\n * 获取某个 phase 的前驱状态(即重置到该 phase 需要设置的状态)。\n * 第一个 phase 的前驱是 BranchCreated;后续 phase 的前驱是上一个 phase 的 approvedState 或 doneState。\n */\n getPhasePreState(phaseName: string): IssueState | undefined {\n const phases = this.def.phases;\n const idx = phases.findIndex(p => p.name === phaseName);\n if (idx < 0) return undefined;\n if (idx === 0) return IssueState.BranchCreated;\n const prev = phases[idx - 1];\n return prev.approvedState ?? prev.doneState;\n }\n\n /**\n * 获取某个 phase 的状态三元组。\n */\n getPhaseStates(phaseName: string): { startState: IssueState; doneState: IssueState; approvedState?: IssueState } | undefined {\n return this.phaseStatesMap.get(phaseName);\n }\n\n // ─── Display helpers (替代 collectStateLabels + derivePhaseStatuses) ───\n\n /**\n * 解析单条状态的展示标签。\n *\n * 对通用状态 PhaseRunning/PhaseDone,需传入 currentPhase 以生成具体标签(如\"分析中\");\n * 缺少 currentPhase 时回退到泛化标签(如\"阶段执行中\")。\n */\n resolveLabel(state: IssueState, currentPhase?: string): string {\n if ((state === IssueState.PhaseRunning || state === IssueState.PhaseDone) && currentPhase) {\n const phaseLabel = t(`pipeline.phase.${currentPhase}`);\n return state === IssueState.PhaseRunning\n ? t('state.phaseDoing', { label: phaseLabel })\n : t('state.phaseDone', { label: phaseLabel });\n }\n if ((state === IssueState.PhaseWaiting || state === IssueState.PhaseApproved) && currentPhase) {\n const phaseLabel = t(`pipeline.phase.${currentPhase}`);\n return state === IssueState.PhaseWaiting\n ? t('state.phaseWaiting', { label: phaseLabel })\n : t('state.phaseApproved', { label: phaseLabel });\n }\n const labels = this.collectStateLabels();\n return labels.get(state) ?? state;\n }\n\n /**\n * 收集所有状态及其展示标签。\n * 为通用状态 PhaseRunning/PhaseDone 生成每个阶段的复合 key 条目。\n */\n collectStateLabels(): Map<string, string> {\n const labels = new Map<string, string>();\n labels.set(IssueState.Pending, t('state.pending'));\n labels.set(IssueState.Skipped, t('state.skipped'));\n labels.set(IssueState.BranchCreated, t('state.branchCreated'));\n\n for (const phase of this.def.phases) {\n const phaseLabel = t(`pipeline.phase.${phase.name}`);\n\n // AI 阶段: PhaseRunning/PhaseDone → composite key\n if (phase.startState === IssueState.PhaseRunning) {\n labels.set(`phase_running:${phase.name}`, t('state.phaseDoing', { label: phaseLabel }));\n } else if (phase.startState === IssueState.PhaseWaiting) {\n // Gate 阶段: PhaseWaiting → composite key\n labels.set(`phase_waiting:${phase.name}`, t('state.phaseWaiting', { label: phaseLabel }));\n } else {\n labels.set(phase.startState, t('state.phaseDoing', { label: phaseLabel }));\n }\n\n if (phase.doneState === IssueState.PhaseDone) {\n labels.set(`phase_done:${phase.name}`, t('state.phaseDone', { label: phaseLabel }));\n } else if (phase.doneState === IssueState.PhaseApproved) {\n // Gate 阶段: PhaseApproved → composite key\n labels.set(`phase_approved:${phase.name}`, t('state.phaseApproved', { label: phaseLabel }));\n } else if (phase.doneState !== IssueState.Completed) {\n labels.set(phase.doneState, t('state.phaseDone', { label: phaseLabel }));\n }\n\n // 非通用 approvedState(保留,支持自定义状态)\n if (phase.approvedState\n && phase.approvedState !== IssueState.PhaseApproved\n && phase.approvedState !== phase.doneState) {\n labels.set(phase.approvedState, t('state.phaseApproved', { label: phaseLabel }));\n }\n }\n\n labels.set(IssueState.Completed, t('state.completed'));\n labels.set(IssueState.Failed, t('state.failed'));\n labels.set(IssueState.ResolvingConflict, t('state.resolvingConflict'));\n return labels;\n }\n\n /**\n * 根据当前 state,推导每个 phase 的进度状态。\n * 支持通用状态 PhaseRunning/PhaseDone + currentPhase。\n */\n derivePhaseStatuses(currentState: string, currentPhase?: string): Record<string, 'pending' | 'in_progress' | 'completed'> {\n const result: Record<string, 'pending' | 'in_progress' | 'completed'> = {};\n let passedCurrent = false;\n\n // 通用阶段状态:基于 currentPhase 名称推导\n if ((currentState === IssueState.PhaseRunning || currentState === IssueState.PhaseDone) && currentPhase) {\n for (const phase of this.def.phases) {\n if (passedCurrent) {\n result[phase.name] = 'pending';\n } else if (phase.name === currentPhase) {\n result[phase.name] = currentState === IssueState.PhaseRunning ? 'in_progress' : 'completed';\n passedCurrent = currentState === IssueState.PhaseRunning;\n // PhaseDone 意味着该阶段完成,后续为 pending\n if (currentState === IssueState.PhaseDone) passedCurrent = true;\n } else {\n result[phase.name] = 'completed';\n }\n }\n return result;\n }\n\n // 通用 gate 阶段状态:基于 currentPhase 名称推导\n if ((currentState === IssueState.PhaseWaiting || currentState === IssueState.PhaseApproved) && currentPhase) {\n for (const phase of this.def.phases) {\n if (passedCurrent) {\n result[phase.name] = 'pending';\n } else if (phase.name === currentPhase) {\n result[phase.name] = currentState === IssueState.PhaseWaiting ? 'in_progress' : 'completed';\n passedCurrent = true;\n } else {\n result[phase.name] = 'completed';\n }\n }\n return result;\n }\n\n // 终态:所有阶段标记为 completed\n if (currentState === IssueState.Completed || currentState === IssueState.ResolvingConflict) {\n for (const phase of this.def.phases) {\n result[phase.name] = 'completed';\n }\n return result;\n }\n\n // 非通用阶段状态(传统 startState/doneState 匹配,如 BranchCreated 等)\n for (const phase of this.def.phases) {\n if (passedCurrent) {\n result[phase.name] = 'pending';\n continue;\n }\n if (phase.startState === currentState) {\n result[phase.name] = 'in_progress';\n passedCurrent = true;\n } else if (phase.doneState === currentState || phase.approvedState === currentState) {\n result[phase.name] = 'completed';\n } else {\n // 未匹配任何阶段的状态(Pending/Skipped/BranchCreated/Failed)→ pending\n result[phase.name] = 'pending';\n }\n }\n return result;\n }\n\n // ─── Pipeline Protocol queries (P1) ───\n\n /**\n * 返回可被用户单独重试的阶段名列表。\n * 优先使用 spec.retryable,未声明时默认 kind === 'ai'。\n */\n getRetryablePhases(): string[] {\n return this.def.phases\n .filter(spec => spec.retryable ?? (spec.kind === 'ai'))\n .map(spec => spec.name);\n }\n\n /**\n * 判断指定阶段是否可重试。\n */\n isRetryable(phaseName: string): boolean {\n const spec = this.def.phases.find(p => p.name === phaseName);\n if (!spec) return false;\n return spec.retryable ?? (spec.kind === 'ai');\n }\n\n /**\n * 查找 gate 类型的阶段。\n */\n getGatePhase(): PhaseSpec | undefined {\n return this.def.phases.find(p => p.kind === 'gate');\n }\n\n /**\n * 判断指定阶段完成后是否应启动预览服务器。\n */\n shouldDeployPreview(phaseName: string): boolean {\n const spec = this.def.phases.find(p => p.name === phaseName);\n return spec?.deploysPreview ?? false;\n }\n\n /**\n * 收集所有阶段的产物文件,扁平化为单一列表。\n */\n collectArtifacts(): PlanFileSpec[] {\n return this.def.phases.flatMap(spec => spec.artifacts ?? []);\n }\n\n /**\n * 返回所有阶段的名称和标签(保持定义顺序)。\n */\n getPhaseDefs(): { name: string; label: string }[] {\n return this.def.phases.map(p => ({ name: p.name, label: p.label }));\n }\n\n /**\n * 返回所有 kind === 'ai' 的阶段名(可执行阶段)。\n */\n getExecutablePhaseNames(): string[] {\n return this.def.phases\n .filter(spec => spec.kind === 'ai')\n .map(spec => spec.name);\n }\n}\n","import { IssueState } from '../tracker/IssueState.js';\nimport { ActionLifecycleManager } from '../lifecycle/ActionLifecycleManager.js';\nimport { PipelineNotFoundError } from '../errors/index.js';\nimport { t } from '../i18n/index.js';\nimport { registerPhase, type PhaseConstructor } from '../phases/PhaseFactory.js';\n\nexport type PipelineMode = string;\nexport type KnownPipelineMode = 'plan-mode';\n\nexport interface PhaseSpec {\n name: string;\n label: string;\n startState: IssueState;\n doneState: IssueState;\n kind: 'ai' | 'gate';\n approvedState?: IssueState;\n /** 此阶段是否可被用户单独重试。默认:kind === 'ai' */\n retryable?: boolean;\n /** 此阶段完成后是否应启动预览服务器。默认:false */\n deploysPreview?: boolean;\n /** 此阶段产出的文件列表。默认:[] */\n artifacts?: PlanFileSpec[];\n}\n\nexport interface PlanFileSpec {\n filename: string;\n label: string;\n editable: boolean;\n}\n\nexport interface PipelineDef {\n mode: PipelineMode;\n phases: PhaseSpec[];\n}\n\n// ---------------------------------------------------------------------------\n// Pipeline Registry\n// ---------------------------------------------------------------------------\n\nconst pipelineRegistry = new Map<string, PipelineDef>();\n\n/**\n * 注册一条流水线定义。可选同时注册其阶段构造器。\n * 重复注册同一 mode 会覆盖。\n */\nexport function registerPipeline(\n def: PipelineDef,\n phases?: Record<string, PhaseConstructor>,\n): void {\n pipelineRegistry.set(def.mode, def);\n if (phases) {\n for (const [name, ctor] of Object.entries(phases)) {\n registerPhase(name, ctor);\n }\n }\n}\n\n/** 获取所有已注册的流水线模式名 */\nexport function getRegisteredModes(): string[] {\n return [...pipelineRegistry.keys()];\n}\n\n/** 获取所有已注册的 PipelineDef */\nexport function getAllPipelineDefs(): PipelineDef[] {\n return [...pipelineRegistry.values()];\n}\n\n/** 用于测试隔离:重置注册表并重新注册内置流水线 */\nexport function _resetPipelineRegistry(): void {\n pipelineRegistry.clear();\n pipelineRegistry.set(PLAN_MODE_PIPELINE.mode, PLAN_MODE_PIPELINE);\n}\n\n// ---------------------------------------------------------------------------\n// Built-in pipeline definitions\n// ---------------------------------------------------------------------------\n\nexport const PLAN_MODE_PIPELINE: PipelineDef = {\n mode: 'plan-mode',\n phases: [\n { name: 'plan', label: '规划', startState: IssueState.PhaseRunning,\n doneState: IssueState.PhaseDone, kind: 'ai',\n artifacts: [{ filename: '01-plan.md', label: '实施计划', editable: true }] },\n { name: 'review', label: '审核', startState: IssueState.PhaseWaiting,\n doneState: IssueState.PhaseApproved, approvedState: IssueState.PhaseApproved,\n kind: 'gate', retryable: false,\n artifacts: [\n { filename: 'review-feedback.md', label: '审核反馈', editable: false },\n { filename: 'review-history.json', label: '审核历史', editable: false },\n ] },\n { name: 'build', label: '实施', startState: IssueState.PhaseRunning,\n doneState: IssueState.PhaseDone, kind: 'ai', deploysPreview: true },\n { name: 'verify', label: '验证', startState: IssueState.PhaseRunning,\n doneState: IssueState.Completed, kind: 'ai',\n artifacts: [{ filename: '02-verify-report.md', label: '验证报告', editable: false }] },\n ],\n};\n\n// Self-register built-in pipelines\npipelineRegistry.set(PLAN_MODE_PIPELINE.mode, PLAN_MODE_PIPELINE);\n\n// ---------------------------------------------------------------------------\n// Lookup functions\n// ---------------------------------------------------------------------------\n\nexport function resolvePipelineMode(aiMode: string, explicit?: string): PipelineMode {\n if (explicit && pipelineRegistry.has(explicit)) return explicit;\n return 'plan-mode';\n}\n\nexport function getPipelineDef(mode: PipelineMode): PipelineDef {\n const def = pipelineRegistry.get(mode);\n if (!def) {\n throw new PipelineNotFoundError(mode);\n }\n return def;\n}\n\n/**\n * 从 PipelineDef 创建 ActionLifecycleManager 实例。\n */\nexport function createLifecycleManager(def: PipelineDef): ActionLifecycleManager {\n return new ActionLifecycleManager(def);\n}\n\nexport function getPhaseLabel(phaseName: string): string {\n return t(`pipeline.phase.${phaseName}`);\n}\n\nexport function getPlanFileLabel(filename: string): string {\n return t(`planFile.${filename}`);\n}\n","import path from 'node:path';\nimport fs from 'node:fs/promises';\nimport { execFile } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { Config } from '../config.js';\nimport { IssueNotFoundError, InvalidPhaseError } from '../errors/index.js';\nimport { GongfengClient, GongfengIssue } from '../clients/GongfengClient.js';\nimport { GitOperations } from '../git/GitOperations.js';\nimport type { AIRunner } from '../ai-runner/index.js';\nimport { IssueTracker } from '../tracker/IssueTracker.js';\nimport { IssueState } from '../tracker/IssueState.js';\nimport type { PipelineModeView } from '../tracker/IssueViews.js';\nimport { PlanPersistence } from '../persistence/PlanPersistence.js';\nimport { WorktreeContext } from '../git/WorktreeContext.js';\nimport { getLocalIP } from '../utils/network.js';\nimport { PhaseContext, PhaseLifecycleHooks } from '../phases/BasePhase.js';\nimport { createPhase } from '../phases/PhaseFactory.js';\nimport { resolvePipelineMode, getPipelineDef, createLifecycleManager, PipelineDef } from '../pipeline/PipelineDefinition.js';\nimport { ActionLifecycleManager } from '../lifecycle/ActionLifecycleManager.js';\nimport { SupplementStore } from '../supplement/SupplementStore.js';\nimport { gongfengIssueToDemandSpec } from '../demand/adapters/GongfengAdapter.js';\nimport { getIid, getExternalId, getTitle } from '../tracker/IssueRecordHelper.js';\nimport { eventBus as defaultEventBus, type EventBus } from '../events/EventBus.js';\nimport { AsyncMutex } from '../utils/AsyncMutex.js';\nimport { extractTapdId, generateMRTitle, generateMRDescription } from '../utils/MergeRequestHelper.js';\nimport { PortAllocator, type PortPair } from '../deploy/PortAllocator.js';\nimport { DevServerManager } from '../deploy/DevServerManager.js';\nimport { isE2eEnabledForIssue } from '../e2e/E2eSettings.js';\nimport { isNoteSyncEnabledForIssue } from '../notesync/NoteSyncSettings.js';\nimport { ScreenshotPublisher } from '../e2e/ScreenshotPublisher.js';\nimport { ConflictResolver } from '../git/ConflictResolver.js';\nimport { getProjectKnowledge } from '../knowledge/index.js';\nimport { KNOWLEDGE_DEFAULTS } from '../knowledge/KnowledgeDefaults.js';\nimport { logger as rootLogger } from '../logger.js';\nimport { runWithIssueContext } from '../context/IssueContext.js';\nimport { metrics } from '../metrics/MetricsCollector.js';\nimport { t } from '../i18n/index.js';\nimport type { OrchestratorDeps, IssueProcessingContext } from './IssueProcessingContext.js';\nimport { executeSetup } from './steps/SetupStep.js';\nimport { executePhaseLoop } from './steps/PhaseLoopStep.js';\nimport { executeCompletion } from './steps/CompletionStep.js';\nimport { handleFailure } from './steps/FailureHandler.js';\n\nexport interface MergeRequestResult {\n url: string;\n iid: number;\n}\n\nconst execFileAsync = promisify(execFile);\nconst logger = rootLogger.child('PipelineOrchestrator');\n\nexport class PipelineOrchestrator {\n private config: Config;\n private gongfeng: GongfengClient;\n private mainGit: GitOperations;\n private aiRunner: AIRunner;\n private tracker: IssueTracker;\n private supplementStore?: SupplementStore;\n private mainGitMutex: AsyncMutex;\n private conflictResolver: ConflictResolver;\n private pipelineDef: PipelineDef;\n private lifecycleManager: ActionLifecycleManager;\n private portAllocator: PortAllocator;\n private devServerManager: DevServerManager;\n private screenshotPublisher: ScreenshotPublisher;\n private eventBus: EventBus;\n private claimer: import('../coordination/IssueClaimer.js').IssueClaimer | null = null;\n\n /** 暴露 AIRunner 给外部(如 CommandExecutor 取消进程时使用) */\n getAIRunner(): AIRunner {\n return this.aiRunner;\n }\n\n /** 替换 AIRunner(用于配置热重载) */\n setAIRunner(runner: AIRunner): void {\n this.aiRunner = runner;\n this.conflictResolver = new ConflictResolver(runner);\n logger.info('AIRunner replaced via hot-reload');\n }\n\n constructor(\n config: Config,\n gongfeng: GongfengClient,\n git: GitOperations,\n aiRunner: AIRunner,\n tracker: IssueTracker,\n supplementStore?: SupplementStore,\n mainGitMutex?: AsyncMutex,\n eventBusInstance?: EventBus,\n ) {\n this.config = config;\n this.gongfeng = gongfeng;\n this.mainGit = git;\n this.aiRunner = aiRunner;\n this.tracker = tracker;\n this.supplementStore = supplementStore;\n this.mainGitMutex = mainGitMutex ?? new AsyncMutex();\n this.eventBus = eventBusInstance ?? defaultEventBus;\n this.conflictResolver = new ConflictResolver(aiRunner);\n\n const mode = resolvePipelineMode(config.ai.mode, config.pipeline?.mode === 'auto' ? undefined : config.pipeline?.mode);\n this.pipelineDef = getPipelineDef(mode);\n this.lifecycleManager = createLifecycleManager(this.pipelineDef);\n logger.info('Pipeline mode resolved', { mode: this.pipelineDef.mode, aiMode: config.ai.mode });\n\n this.portAllocator = new PortAllocator({\n backendPortBase: config.e2e.backendPortBase,\n frontendPortBase: config.e2e.frontendPortBase,\n });\n this.devServerManager = new DevServerManager();\n this.screenshotPublisher = new ScreenshotPublisher(gongfeng);\n\n this.restorePortAllocations();\n }\n\n getPortAllocator(): PortAllocator { return this.portAllocator; }\n getDevServerManager(): DevServerManager { return this.devServerManager; }\n getMainGitMutex(): AsyncMutex { return this.mainGitMutex; }\n\n /** 注入 IssueClaimer 实例(在 index.ts 中获取 currentUser 后调用) */\n setClaimer(claimer: import('../coordination/IssueClaimer.js').IssueClaimer | null): void {\n this.claimer = claimer;\n }\n\n async cleanupStaleState(): Promise<void> {\n logger.info('Cleaning up stale worktree state...');\n let cleaned = 0;\n\n try {\n const worktrees = await this.mainGit.worktreeList();\n for (const wtDir of worktrees) {\n // Skip the main worktree\n if (wtDir === this.config.project.gitRootDir) continue;\n if (!wtDir.includes('/issue-')) continue;\n\n try {\n // Check if .git file exists — if missing, the worktree is corrupted\n const gitFile = path.join(wtDir, '.git');\n try {\n await fs.access(gitFile);\n } catch {\n logger.warn('Worktree corrupted (.git missing), force removing', { dir: wtDir });\n await this.mainGit.worktreeRemove(wtDir, true).catch(() => {});\n await this.mainGit.worktreePrune();\n cleaned++;\n continue;\n }\n\n const wtGit = new GitOperations(wtDir);\n\n // Abort residual rebase\n if (await wtGit.isRebaseInProgress()) {\n logger.warn('Aborting residual rebase in worktree', { dir: wtDir });\n await wtGit.rebaseAbort();\n cleaned++;\n }\n\n // Clean up .git/index.lock\n const indexLock = path.join(wtDir, '.git', 'index.lock');\n try {\n await fs.unlink(indexLock);\n logger.warn('Removed stale index.lock', { path: indexLock });\n cleaned++;\n } catch {\n // No lock file — this is the normal case\n }\n } catch (err) {\n logger.warn('Failed to clean worktree state', { dir: wtDir, error: (err as Error).message });\n }\n }\n } catch (err) {\n logger.warn('Failed to list worktrees for cleanup', { error: (err as Error).message });\n }\n\n // Clean up main repo index.lock\n const mainIndexLock = path.join(this.config.project.gitRootDir, '.git', 'index.lock');\n try {\n await fs.unlink(mainIndexLock);\n logger.warn('Removed stale main repo index.lock', { path: mainIndexLock });\n cleaned++;\n } catch {\n // No lock file — normal\n }\n\n logger.info('Stale state cleanup complete', { cleaned });\n }\n\n private restorePortAllocations(): void {\n for (const record of this.tracker.getAll()) {\n if (record.ports) {\n this.portAllocator.restore(getIid(record), record.ports);\n }\n }\n }\n\n getPipelineDef(): PipelineDef {\n return this.pipelineDef;\n }\n\n private emitProgress(issueIid: number, step: string, message: string): void {\n this.eventBus.emitTyped('pipeline:progress', { issueIid, step, message });\n }\n\n private computeWorktreeContext(issueIid: number, branchName: string): WorktreeContext {\n const gitRootDir = path.join(this.config.project.worktreeBaseDir, `issue-${issueIid}`);\n const workDir = path.join(gitRootDir, this.config.project.projectSubDir);\n return { gitRootDir, workDir, branchName, issueIid };\n }\n\n private async ensureWorktree(wtCtx: WorktreeContext): Promise<void> {\n const worktrees = await this.mainGit.worktreeList();\n if (worktrees.includes(wtCtx.gitRootDir)) {\n // Validate that the .git file exists — if missing, the worktree is corrupted\n const gitFile = path.join(wtCtx.gitRootDir, '.git');\n try {\n await fs.access(gitFile);\n logger.info('Reusing existing worktree', { dir: wtCtx.gitRootDir });\n return;\n } catch {\n logger.warn('Worktree registered but .git missing, recreating', { dir: wtCtx.gitRootDir });\n await this.mainGit.worktreeRemove(wtCtx.gitRootDir, true);\n await this.mainGit.worktreePrune();\n }\n }\n\n await this.cleanStaleWorktreeDir(wtCtx.gitRootDir);\n\n const localExists = await this.mainGit.branchExists(wtCtx.branchName);\n if (localExists) {\n await this.mainGit.worktreeAddExisting(wtCtx.gitRootDir, wtCtx.branchName);\n return;\n }\n\n const remoteExists = await this.mainGit.remoteBranchExists(wtCtx.branchName);\n if (remoteExists) {\n await this.mainGit.worktreeAddTracking(wtCtx.gitRootDir, wtCtx.branchName);\n return;\n }\n\n await this.mainGit.worktreeAdd(\n wtCtx.gitRootDir,\n wtCtx.branchName,\n `origin/${this.config.project.baseBranch}`,\n );\n }\n\n private async cleanStaleWorktreeDir(dir: string): Promise<void> {\n try {\n await fs.access(dir);\n } catch {\n return;\n }\n logger.warn('Removing stale worktree directory not tracked by git', { dir });\n await fs.rm(dir, { recursive: true, force: true });\n await this.mainGit.worktreePrune();\n }\n\n private async cleanupWorktree(wtCtx: WorktreeContext): Promise<void> {\n try {\n await this.mainGit.worktreeRemove(wtCtx.gitRootDir, true);\n logger.info('Worktree cleaned up', { dir: wtCtx.gitRootDir });\n } catch (err) {\n logger.warn('Failed to cleanup worktree', { dir: wtCtx.gitRootDir, error: (err as Error).message });\n }\n }\n\n private async installDependencies(workDir: string): Promise<void> {\n logger.info('Installing dependencies in worktree', { workDir });\n\n const knowledge = getProjectKnowledge() ?? KNOWLEDGE_DEFAULTS;\n const pkgMgr = knowledge.toolchain.packageManager.toLowerCase();\n const isNodeProject = ['npm', 'pnpm', 'yarn', 'bun'].some(m => pkgMgr.includes(m));\n\n if (isNodeProject) {\n const ready = await this.ensureNodeModules(workDir);\n if (ready) {\n logger.info('node_modules ready — skipping install');\n return;\n }\n }\n\n const installCmd = knowledge.toolchain.installCommand;\n const fallbackCmd = knowledge.toolchain.installFallbackCommand;\n const [bin, ...args] = installCmd.split(/\\s+/);\n\n try {\n await execFileAsync(bin, args, {\n cwd: workDir,\n maxBuffer: 10 * 1024 * 1024,\n timeout: 300_000,\n });\n logger.info('Dependencies installed');\n } catch (err) {\n if (fallbackCmd) {\n logger.warn(`${installCmd} failed, retrying with fallback command`, {\n error: (err as Error).message,\n });\n const [fallbackBin, ...fallbackArgs] = fallbackCmd.split(/\\s+/);\n try {\n await execFileAsync(fallbackBin, fallbackArgs, {\n cwd: workDir,\n maxBuffer: 10 * 1024 * 1024,\n timeout: 300_000,\n });\n logger.info('Dependencies installed (fallback)');\n } catch (retryErr) {\n logger.warn('Fallback install also failed', {\n error: (retryErr as Error).message,\n });\n }\n } else {\n logger.warn('Install failed, no fallback configured', {\n error: (err as Error).message,\n });\n }\n }\n }\n\n private async ensureNodeModules(workDir: string): Promise<boolean> {\n const targetBin = path.join(workDir, 'node_modules', '.bin');\n try {\n await fs.access(targetBin);\n logger.info('node_modules already complete (has .bin/)');\n return true;\n } catch {\n // .bin/ missing — need to seed or install\n }\n\n const sourceNM = path.join(this.config.project.workDir, 'node_modules');\n const targetNM = path.join(workDir, 'node_modules');\n try {\n await fs.access(sourceNM);\n } catch {\n logger.warn('Main repo node_modules not found, skipping seed', { sourceNM });\n return false;\n }\n\n logger.info('Seeding node_modules from main repo via reflink copy', { sourceNM, targetNM });\n try {\n await execFileAsync('rm', ['-rf', targetNM], { timeout: 60_000 });\n // btrfs reflink: zero-copy CoW, near-instant; falls back to regular copy on non-btrfs\n await execFileAsync('cp', ['-a', '--reflink=auto', sourceNM, targetNM], {\n timeout: 120_000,\n });\n logger.info('node_modules seeded from main repo');\n return true;\n } catch (err) {\n logger.warn('Failed to seed node_modules from main repo', {\n error: (err as Error).message,\n });\n return false;\n }\n }\n\n async restartIssue(issueIid: number): Promise<void> {\n const record = this.tracker.get(issueIid);\n if (!record) throw new IssueNotFoundError(issueIid);\n\n const wtCtx = this.computeWorktreeContext(issueIid, record.branchName);\n logger.info('Restarting issue — cleaning context', { issueIid, branchName: record.branchName });\n\n this.aiRunner.killByWorkDir(wtCtx.workDir);\n\n this.stopPreviewServers(issueIid);\n\n try {\n const deleted = await this.gongfeng.cleanupAgentNotes(getExternalId(record));\n logger.info('Agent notes cleaned up', { issueIid, deleted });\n } catch (err) {\n logger.warn('Failed to cleanup agent notes', { issueIid, error: (err as Error).message });\n }\n\n await this.mainGitMutex.runExclusive(async () => {\n await this.cleanupWorktree(wtCtx);\n try { await this.mainGit.deleteBranch(record.branchName); } catch { /* branch may not exist */ }\n try { await this.mainGit.deleteRemoteBranch(record.branchName); } catch { /* remote branch may not exist */ }\n });\n\n this.tracker.resetFull(issueIid);\n logger.info('Issue restarted', { issueIid });\n }\n\n async cancelIssue(issueIid: number): Promise<void> {\n const record = this.tracker.get(issueIid);\n if (!record) throw new IssueNotFoundError(issueIid);\n\n const wtCtx = this.computeWorktreeContext(issueIid, record.branchName);\n logger.info('Cancelling issue — cleaning all resources', { issueIid, branchName: record.branchName });\n\n // 1. 终止 AI 进程\n this.aiRunner.killByWorkDir(wtCtx.workDir);\n\n // 2. 停止预览服务器\n this.stopPreviewServers(issueIid);\n\n // 3. 移除工蜂标签(关键步骤!防止 discovery 循环重新发现)\n try {\n await this.gongfeng.removeLabelsWithPrefix(getExternalId(record), 'auto-finish');\n } catch (err) {\n logger.warn('Failed to remove labels on cancel', { issueIid, error: (err as Error).message });\n }\n\n // 4. 清理 worktree + 分支\n await this.mainGitMutex.runExclusive(async () => {\n await this.cleanupWorktree(wtCtx);\n try { await this.mainGit.deleteBranch(record.branchName); } catch { /* branch may not exist */ }\n try { await this.mainGit.deleteRemoteBranch(record.branchName); } catch { /* remote branch may not exist */ }\n });\n\n // 5. 删除 tracker 记录\n this.tracker.delete(issueIid);\n logger.info('Issue cancelled', { issueIid });\n }\n\n retryFromPhase(issueIid: number, phase: string): void {\n const record = this.tracker.get(issueIid);\n if (!record) throw new IssueNotFoundError(issueIid);\n\n const issueDef = this.getIssueSpecificPipelineDef(record);\n const issueLM = createLifecycleManager(issueDef);\n if (!issueLM.isRetryable(phase)) {\n throw new InvalidPhaseError(phase);\n }\n\n logger.info('Retrying issue from phase', { issueIid, phase });\n this.tracker.resetToPhase(issueIid, phase, issueDef);\n }\n\n private getIssueSpecificPipelineDef(record: PipelineModeView): PipelineDef {\n if (record.pipelineMode) {\n return getPipelineDef(record.pipelineMode);\n }\n return this.pipelineDef;\n }\n\n async processIssue(issue: GongfengIssue): Promise<void> {\n return runWithIssueContext(issue.iid, () => this._processIssueImpl(issue));\n }\n\n private buildDeps(): OrchestratorDeps {\n return {\n config: this.config,\n gongfeng: this.gongfeng,\n mainGit: this.mainGit,\n mainGitMutex: this.mainGitMutex,\n aiRunner: this.aiRunner,\n tracker: this.tracker,\n supplementStore: this.supplementStore,\n screenshotPublisher: this.screenshotPublisher,\n portAllocator: this.portAllocator,\n devServerManager: this.devServerManager,\n eventBus: this.eventBus,\n claimer: this.claimer,\n emitProgress: (iid, step, msg) => this.emitProgress(iid, step, msg),\n ensureWorktree: (wtCtx) => this.ensureWorktree(wtCtx),\n installDependencies: (workDir) => this.installDependencies(workDir),\n buildPhaseHooks: (iid, issueId) => this.buildPhaseHooks(iid, issueId),\n shouldAutoApprove: (labels) => this.shouldAutoApprove(labels),\n shouldDeployServers: (iid) => this.shouldDeployServers(iid),\n startPreviewServers: (wtCtx, issue) => this.startPreviewServers(wtCtx, issue),\n stopPreviewServers: (iid) => this.stopPreviewServers(iid),\n tryCreateMergeRequest: (issue, branch, workDir, previewUrl) =>\n this.tryCreateMergeRequest(issue, branch, workDir, previewUrl),\n buildPreviewUrl: (iid) => this.buildPreviewUrl(iid),\n };\n }\n\n private async _processIssueImpl(issue: GongfengIssue): Promise<void> {\n const branchName = `${this.config.project.branchPrefix}-${issue.iid}`;\n const wtCtx = this.computeWorktreeContext(issue.iid, branchName);\n\n logger.info('Processing issue', { iid: issue.iid, title: issue.title, branchName, worktree: wtCtx.gitRootDir });\n metrics.incCounter('iaf_issues_total', { pipeline: this.pipelineDef.mode });\n\n const supplement = this.supplementStore?.get(issue.iid);\n const demand = gongfengIssueToDemandSpec(issue, supplement);\n\n let record = this.tracker.get(issue.iid);\n const isRetry = record?.state === IssueState.Failed;\n if (isRetry) {\n metrics.incCounter('iaf_issues_retried_total');\n }\n\n if (!record) {\n record = this.tracker.create({\n state: IssueState.Pending,\n branchName,\n pipelineMode: this.pipelineDef.mode,\n demandSpec: demand,\n });\n }\n\n if (!record.pipelineMode) {\n this.tracker.updateState(issue.iid, record.state, { pipelineMode: this.pipelineDef.mode } as any);\n record.pipelineMode = this.pipelineDef.mode;\n }\n\n const issuePipelineDef = this.getIssueSpecificPipelineDef(record);\n const issueLM = createLifecycleManager(issuePipelineDef);\n const phaseCtx: PhaseContext = { demand, branchName, pipelineMode: issuePipelineDef.mode };\n\n const ctx: IssueProcessingContext = {\n issue, branchName, wtCtx, record, isRetry,\n pipelineDef: issuePipelineDef,\n lifecycleManager: issueLM,\n demand, phaseCtx,\n };\n\n const deps = this.buildDeps();\n\n try {\n const { wtGit, wtPlan } = await executeSetup(ctx, deps);\n const phaseResult = await executePhaseLoop(ctx, deps, wtGit, wtPlan);\n if (phaseResult.paused) return;\n await executeCompletion(ctx, deps, phaseResult);\n } catch (err) {\n await handleFailure(err, issue, wtCtx, deps);\n }\n }\n\n private async tryCreateMergeRequest(\n issue: GongfengIssue,\n branchName: string,\n workDir: string,\n previewUrl?: string | null,\n ): Promise<MergeRequestResult | null> {\n try {\n const supplement = this.supplementStore?.get(issue.iid);\n const tapdId = supplement?.tapdId?.trim()\n || extractTapdId(issue.description || '');\n\n const title = generateMRTitle(issue.iid, issue.title, tapdId);\n let description = generateMRDescription({\n issueIid: issue.iid,\n issueTitle: issue.title,\n issueDescription: issue.description || '',\n branchName,\n planDir: workDir,\n });\n\n if (previewUrl) {\n description += `\\n\\n## Preview Environment\\n\\n🌐 ${previewUrl}`;\n }\n\n const mr = await this.gongfeng.createMergeRequest({\n sourceBranch: branchName,\n targetBranch: this.config.project.baseBranch,\n title,\n description,\n });\n\n logger.info('Merge request created successfully', {\n iid: issue.iid, mrIid: mr.iid, mrUrl: mr.web_url,\n });\n return { url: mr.web_url, iid: mr.iid };\n } catch (err) {\n const errorMsg = (err as Error).message;\n logger.warn('Failed to create merge request, trying to find existing one', {\n iid: issue.iid, error: errorMsg,\n });\n\n if (errorMsg.includes('already exists')) {\n return this.tryFindExistingMergeRequest(issue.iid, branchName);\n }\n return null;\n }\n }\n\n private async tryFindExistingMergeRequest(\n issueIid: number,\n branchName: string,\n ): Promise<MergeRequestResult | null> {\n try {\n const existing = await this.gongfeng.findMergeRequestByBranch(\n branchName,\n this.config.project.baseBranch,\n );\n if (existing) {\n logger.info('Found existing merge request', {\n iid: issueIid, mrIid: existing.iid, mrUrl: existing.web_url,\n });\n return { url: existing.web_url, iid: existing.iid };\n }\n } catch (findErr) {\n logger.warn('Failed to find existing merge request', {\n iid: issueIid, error: (findErr as Error).message,\n });\n }\n return null;\n }\n\n private shouldDeployServers(issueIid: number): boolean {\n return isE2eEnabledForIssue(issueIid, this.tracker, this.config)\n || this.config.preview.enabled;\n }\n\n private shouldAutoApprove(issueLabels: string[]): boolean {\n const autoLabels = this.config.review.autoApproveLabels;\n if (!autoLabels.length) return false;\n return issueLabels.some(l => autoLabels.includes(l));\n }\n\n private buildPhaseHooks(iid: number, issueId: number): PhaseLifecycleHooks {\n return {\n onPhaseStart: async (phase) => {\n this.tracker.updateState(iid, IssueState.PhaseRunning, { currentPhase: phase });\n },\n onPhaseDone: async (phase) => {\n this.tracker.updateState(iid, IssueState.PhaseDone, { currentPhase: phase });\n },\n onPhaseFailed: async (_phase, error) => {\n this.tracker.markFailed(iid, error, IssueState.PhaseRunning);\n },\n onComment: async (msg) => {\n try { await this.gongfeng.createIssueNote(issueId, msg); } catch { /* ignore */ }\n },\n isNoteSyncEnabled: () => isNoteSyncEnabledForIssue(iid, this.tracker, this.config),\n isE2eEnabled: () => isE2eEnabledForIssue(iid, this.tracker, this.config),\n };\n }\n\n private async startPreviewServers(\n wtCtx: WorktreeContext,\n issue: GongfengIssue,\n ): Promise<PortPair | null> {\n try {\n this.emitProgress(issue.iid, 'deploy', t('orchestrator.deployProgress'));\n const ports = await this.portAllocator.allocate(issue.iid);\n wtCtx.ports = ports;\n\n this.tracker.updateState(issue.iid, this.tracker.get(issue.iid)!.state, {\n ports,\n previewStartedAt: new Date().toISOString(),\n } as any);\n\n await this.devServerManager.startServers(wtCtx, ports);\n\n const previewUrl = this.buildPreviewUrl(issue.iid);\n if (previewUrl) {\n try {\n await this.gongfeng.createIssueNote(\n issue.id,\n this.buildPreviewComment(ports, previewUrl),\n );\n } catch {\n // ignore comment failure\n }\n }\n\n this.emitProgress(issue.iid, 'deploy_done', t('orchestrator.deployDoneProgress', { url: previewUrl ?? 'N/A' }));\n this.eventBus.emitTyped('pipeline:progress', {\n issueIid: issue.iid,\n step: 'preview_ready',\n message: previewUrl ?? '',\n });\n\n return ports;\n } catch (err) {\n logger.error('Failed to start preview servers', {\n iid: issue.iid,\n error: (err as Error).message,\n });\n return null;\n }\n }\n\n stopPreviewServers(issueIid: number): void {\n this.devServerManager.stopServers(issueIid);\n this.portAllocator.release(issueIid);\n const record = this.tracker.get(issueIid);\n if (record?.ports) {\n this.tracker.updateState(issueIid, record.state, {\n ports: undefined,\n previewStartedAt: undefined,\n } as any);\n }\n }\n\n getPreviewHost(): string {\n if (this.config.preview.host) return this.config.preview.host;\n return getLocalIP();\n }\n\n buildPreviewUrl(issueIid: number): string | null {\n const ports = this.portAllocator.getPortsForIssue(issueIid);\n if (!ports) return null;\n const host = this.getPreviewHost();\n return `https://${host}:${ports.frontendPort}`;\n }\n\n private buildPreviewComment(ports: PortPair, previewUrl: string): string {\n const host = this.getPreviewHost();\n const ttlHours = Math.round(this.config.preview.ttlMs / (60 * 60 * 1000));\n return [\n t('orchestrator.previewComment.title'),\n '',\n t('orchestrator.previewComment.tableHeader'),\n t('orchestrator.previewComment.tableSep'),\n `| ${t('orchestrator.previewComment.frontend')} | ${previewUrl} |`,\n `| ${t('orchestrator.previewComment.backendApi')} | http://${host}:${ports.backendPort}/api |`,\n '',\n t('orchestrator.previewComment.hint'),\n t('orchestrator.previewComment.expiry', { hours: ttlHours }),\n ].join('\\n');\n }\n\n async resolveConflict(issueIid: number): Promise<void> {\n const record = this.tracker.get(issueIid);\n if (!record) throw new IssueNotFoundError(issueIid);\n\n const baseBranch = this.config.project.baseBranch;\n const branchName = record.branchName;\n\n logger.info('Starting conflict resolution', { issueIid, branchName, baseBranch });\n\n // 1. Update state\n this.tracker.updateState(issueIid, IssueState.ResolvingConflict);\n this.eventBus.emitTyped('conflict:started', { issueIid });\n\n // 2. Comment on issue\n try {\n await this.gongfeng.createIssueNote(\n getExternalId(record),\n t('conflict.startComment', { branch: branchName, baseBranch }),\n );\n } catch { /* ignore */ }\n\n const wtCtx = this.computeWorktreeContext(issueIid, branchName);\n\n try {\n // 3. Fetch + ensure worktree\n await this.mainGitMutex.runExclusive(async () => {\n await this.mainGit.fetch();\n await this.ensureWorktree(wtCtx);\n });\n\n const wtGit = new GitOperations(wtCtx.gitRootDir);\n\n // 4. Checkout branch\n await wtGit.checkout(branchName);\n\n // 5–6. Rebase + resolve conflicts using shared ConflictResolver\n await this.conflictResolver.resolve({\n wtGit,\n targetRef: `origin/${baseBranch}`,\n workDir: wtCtx.workDir,\n branchName,\n contextId: issueIid,\n phaseTimeoutMs: this.config.ai.phaseTimeoutMs,\n onEvent: (event) => {\n this.eventBus.emitTyped('agent:output', {\n issueIid,\n phase: 'conflict-resolve',\n event,\n });\n },\n });\n\n // If resolve() returned without throwing, rebase succeeded (with or without conflict resolution).\n\n // 7. Run verification\n logger.info('Running verification after conflict resolution', { issueIid });\n const wtPlan = new PlanPersistence(wtCtx.workDir, issueIid);\n wtPlan.ensureDir();\n\n const conflictLM = createLifecycleManager(this.getIssueSpecificPipelineDef(record));\n const conflictHooks = this.buildPhaseHooks(issueIid, getExternalId(record));\n const verifyPhase = createPhase('verify', this.aiRunner, wtGit, wtPlan, this.config, conflictLM, conflictHooks);\n\n const verifyCtx: PhaseContext = {\n demand: {\n demandId: `gf-${issueIid}`,\n sourceRef: {\n source: 'gongfeng-issue',\n externalId: String(getExternalId(record)),\n displayId: String(issueIid),\n },\n title: getTitle(record),\n description: '',\n createdAt: record.createdAt,\n },\n branchName,\n pipelineMode: record.pipelineMode,\n };\n\n await verifyPhase.execute(verifyCtx);\n\n // 8. Force push\n await wtGit.forcePush(branchName);\n\n // 9. Update state\n this.tracker.updateState(issueIid, IssueState.Completed);\n this.eventBus.emitTyped('conflict:resolved', { issueIid });\n\n // 10. Comment on Issue/MR\n try {\n await this.gongfeng.createIssueNote(\n getExternalId(record),\n t('conflict.resolvedComment', { branch: branchName, baseBranch }),\n );\n } catch { /* ignore */ }\n\n await this.commentOnMr(record.mrUrl, t('conflict.mrResolvedComment'));\n\n logger.info('Conflict resolution completed', { issueIid });\n } catch (err) {\n const errorMsg = (err as Error).message;\n logger.error('Conflict resolution failed', { issueIid, error: errorMsg });\n\n // Try to abort any in-progress rebase\n try {\n const wtGit = new GitOperations(wtCtx.gitRootDir);\n if (await wtGit.isRebaseInProgress()) {\n await wtGit.rebaseAbort();\n }\n } catch { /* ignore abort failure */ }\n\n this.tracker.markFailed(issueIid, errorMsg.slice(0, 500), IssueState.ResolvingConflict);\n this.eventBus.emitTyped('conflict:failed', { issueIid, error: errorMsg });\n\n try {\n await this.gongfeng.createIssueNote(\n getExternalId(record),\n t('conflict.failedComment', { error: errorMsg }),\n );\n } catch { /* ignore */ }\n }\n }\n\n private extractMrIidFromUrl(mrUrl: string): number | null {\n const match = mrUrl.match(/merge_requests\\/(\\d+)/);\n return match ? parseInt(match[1], 10) : null;\n }\n\n private async commentOnMr(mrUrl: string | undefined, body: string): Promise<void> {\n if (!mrUrl) return;\n const mrIid = this.extractMrIidFromUrl(mrUrl);\n if (!mrIid) return;\n try {\n await this.gongfeng.createMergeRequestNote(mrIid, body);\n } catch (err) {\n logger.warn('Failed to comment on MR', { mrIid, error: (err as Error).message });\n }\n }\n}\n","import type { GongfengIssue } from '../../clients/GongfengClient.js';\nimport type { DemandSpec } from '../DemandSpec.js';\nimport type { SupplementInfo } from '../../supplement/SupplementStore.js';\n\n/**\n * 将工蜂 Issue 转换为 DemandSpec 值对象。\n *\n * @param issue 工蜂 Issue 原始数据\n * @param supplement 可选的补充信息(来自 SupplementStore)\n */\nexport function gongfengIssueToDemandSpec(\n issue: GongfengIssue,\n supplement?: SupplementInfo | null,\n): DemandSpec {\n return {\n demandId: `gf-${issue.iid}`,\n sourceRef: {\n source: 'gongfeng-issue',\n externalId: String(issue.id),\n displayId: String(issue.iid),\n },\n title: issue.title,\n description: issue.description ?? '',\n supplement: supplement ? mapSupplement(supplement) : undefined,\n createdAt: issue.created_at ?? new Date().toISOString(),\n };\n}\n\nfunction mapSupplement(s: SupplementInfo): DemandSpec['supplement'] {\n const result: Record<string, string | undefined> = {};\n if (s.requirements?.trim()) result.requirements = s.requirements.trim();\n if (s.acceptanceCriteria?.trim()) result.acceptanceCriteria = s.acceptanceCriteria.trim();\n if (s.scope?.trim()) result.scope = s.scope.trim();\n if (s.constraints?.trim()) result.constraints = s.constraints.trim();\n if (s.references?.trim()) result.references = s.references.trim();\n if (s.freeText?.trim()) result.freeText = s.freeText.trim();\n if (s.tapdId?.trim()) result.tapdId = s.tapdId.trim();\n return Object.keys(result).length > 0 ? result : undefined;\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { t } from '../i18n/index.js';\n\nconst TAPD_PATTERNS = [\n /--story=(\\d+)/i,\n /--bug=(\\d+)/i,\n /tapd[:\\s-]+(\\d+)/i,\n /tapd单号[:\\s]*(\\d+)/i,\n];\n\nexport function extractTapdId(text: string): string | null {\n for (const pattern of TAPD_PATTERNS) {\n const match = text.match(pattern);\n if (match) return match[1];\n }\n return null;\n}\n\nexport function generateMRTitle(issueIid: number, issueTitle: string, tapdId?: string | null): string {\n const base = `feat(#${issueIid}): ${issueTitle}`;\n if (tapdId) {\n return `${base} --story=${tapdId}`;\n }\n return base;\n}\n\nexport function generateMRDescription(options: {\n issueIid: number;\n issueTitle: string;\n issueDescription: string;\n branchName: string;\n planDir?: string;\n}): string {\n const { issueIid, issueTitle, issueDescription, branchName, planDir } = options;\n\n const sections: string[] = [\n t('mr.relatedIssue'),\n ``,\n `- Issue: #${issueIid}`,\n `- ${t('mr.title')}: ${issueTitle}`,\n `- ${t('mr.branch')}: \\`${branchName}\\``,\n ``,\n t('mr.issueDescription'),\n ``,\n issueDescription || t('mr.noDescription'),\n ];\n\n if (planDir) {\n const summaryFiles = [\n { filename: '01-analysis.md', label: t('mr.summaryFiles.01-analysis.md') },\n { filename: '01-plan.md', label: t('mr.summaryFiles.01-plan.md') },\n { filename: '02-design.md', label: t('mr.summaryFiles.02-design.md') },\n { filename: '04-verify-report.md', label: t('mr.summaryFiles.04-verify-report.md') },\n { filename: '02-verify-report.md', label: t('mr.summaryFiles.02-verify-report.md') },\n ];\n\n const planSections: string[] = [];\n for (const { filename, label } of summaryFiles) {\n const filePath = path.join(planDir, '.claude-plan', `issue-${issueIid}`, filename);\n if (fs.existsSync(filePath)) {\n const content = fs.readFileSync(filePath, 'utf-8');\n const summary = extractSummary(content);\n if (summary) {\n planSections.push(`### ${label}\\n\\n${summary}`);\n }\n }\n }\n\n if (planSections.length > 0) {\n sections.push('', t('mr.aiSummary'), '', ...planSections);\n }\n }\n\n sections.push('', '---', t('mr.autoCreated'));\n return sections.join('\\n');\n}\n\nfunction extractSummary(content: string, maxLines = 20): string {\n const lines = content.split('\\n');\n if (lines.length <= maxLines) return content.trim();\n return lines.slice(0, maxLines).join('\\n').trim() + '\\n\\n' + t('mr.truncated');\n}\n","import net from 'node:net';\nimport { PortExhaustionError } from '../errors/index.js';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('PortAllocator');\n\nexport interface PortPair {\n backendPort: number;\n frontendPort: number;\n}\n\nexport interface PortAllocatorOptions {\n backendPortBase: number;\n frontendPortBase: number;\n maxPorts: number;\n}\n\nconst DEFAULT_OPTIONS: PortAllocatorOptions = {\n backendPortBase: 4000,\n frontendPortBase: 9000,\n maxPorts: 100,\n};\n\nfunction checkPortAvailable(port: number): Promise<boolean> {\n return new Promise((resolve) => {\n const server = net.createServer();\n server.once('error', () => resolve(false));\n server.once('listening', () => {\n server.close(() => resolve(true));\n });\n server.listen(port, '0.0.0.0');\n });\n}\n\nexport class PortAllocator {\n private allocated = new Map<number, PortPair>();\n private options: PortAllocatorOptions;\n\n constructor(options?: Partial<PortAllocatorOptions>) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n }\n\n async allocate(issueIid: number): Promise<PortPair> {\n const existing = this.allocated.get(issueIid);\n if (existing) {\n logger.info('Returning already allocated ports', { issueIid, ports: existing });\n return existing;\n }\n\n const usedBackend = new Set([...this.allocated.values()].map((p) => p.backendPort));\n const usedFrontend = new Set([...this.allocated.values()].map((p) => p.frontendPort));\n\n for (let offset = 1; offset <= this.options.maxPorts; offset++) {\n const backendPort = this.options.backendPortBase + offset;\n const frontendPort = this.options.frontendPortBase + offset;\n\n if (usedBackend.has(backendPort) || usedFrontend.has(frontendPort)) {\n continue;\n }\n\n const [beOk, feOk] = await Promise.all([\n checkPortAvailable(backendPort),\n checkPortAvailable(frontendPort),\n ]);\n\n if (beOk && feOk) {\n const pair: PortPair = { backendPort, frontendPort };\n this.allocated.set(issueIid, pair);\n logger.info('Ports allocated', { issueIid, ...pair });\n return pair;\n }\n\n logger.debug('Port pair unavailable, trying next', {\n backendPort,\n frontendPort,\n beOk,\n feOk,\n });\n }\n\n throw new PortExhaustionError(\n `No available port pair found for issue #${issueIid} ` +\n `(scanned ${this.options.maxPorts} offsets from ` +\n `backend=${this.options.backendPortBase} frontend=${this.options.frontendPortBase})`,\n );\n }\n\n release(issueIid: number): void {\n const pair = this.allocated.get(issueIid);\n if (pair) {\n this.allocated.delete(issueIid);\n logger.info('Ports released', { issueIid, ...pair });\n }\n }\n\n getPortsForIssue(issueIid: number): PortPair | undefined {\n return this.allocated.get(issueIid);\n }\n\n getAllAllocated(): Map<number, PortPair> {\n return new Map(this.allocated);\n }\n\n restore(issueIid: number, ports: PortPair): void {\n this.allocated.set(issueIid, ports);\n logger.info('Ports restored from persistence', { issueIid, ...ports });\n }\n}\n","import { spawn, ChildProcess } from 'node:child_process';\nimport path from 'node:path';\nimport https from 'node:https';\nimport http from 'node:http';\nimport type { PortPair } from './PortAllocator.js';\nimport type { WorktreeContext } from '../git/WorktreeContext.js';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('DevServerManager');\n\ninterface ServerSet {\n backend: ChildProcess;\n frontend: ChildProcess;\n ports: PortPair;\n workDir: string;\n startedAt: string;\n}\n\nexport interface DevServerManagerOptions {\n healthCheckTimeoutMs: number;\n healthCheckIntervalMs: number;\n backendCommand?: { bin: string; args: string[] };\n frontendCommand?: { bin: string; args: string[] };\n}\n\nconst DEFAULT_OPTIONS: DevServerManagerOptions = {\n healthCheckTimeoutMs: 120_000,\n healthCheckIntervalMs: 3_000,\n};\n\nfunction waitForPort(\n port: number,\n useTls: boolean,\n timeoutMs: number,\n intervalMs: number,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const deadline = Date.now() + timeoutMs;\n\n const check = () => {\n if (Date.now() > deadline) {\n reject(new Error(`Port ${port} not ready after ${timeoutMs}ms`));\n return;\n }\n\n const req = useTls\n ? https.get(\n { hostname: '127.0.0.1', port, path: '/', rejectUnauthorized: false, timeout: 5_000 },\n (res) => { res.resume(); resolve(); },\n )\n : http.get(\n { hostname: '127.0.0.1', port, path: '/', timeout: 5_000 },\n (res) => { res.resume(); resolve(); },\n );\n\n req.on('error', () => {\n setTimeout(check, intervalMs);\n });\n req.on('timeout', () => {\n req.destroy();\n setTimeout(check, intervalMs);\n });\n };\n\n check();\n });\n}\n\nexport class DevServerManager {\n private servers = new Map<number, ServerSet>();\n private options: DevServerManagerOptions;\n\n constructor(options?: Partial<DevServerManagerOptions>) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n }\n\n async startServers(wtCtx: WorktreeContext, ports: PortPair): Promise<void> {\n if (this.servers.has(wtCtx.issueIid)) {\n logger.info('Servers already running for issue', { issueIid: wtCtx.issueIid });\n return;\n }\n\n logger.info('Starting dev servers', { issueIid: wtCtx.issueIid, ...ports });\n\n const backendEnv: Record<string, string> = {\n ...process.env as Record<string, string>,\n PORT: String(ports.backendPort),\n E2E_PORT_OVERRIDE: '1',\n ENV_PATH: '.env.development.local',\n };\n\n const backendCmd = this.options.backendCommand ?? { bin: 'node', args: ['ace', 'serve', '--watch'] };\n const backend = spawn(backendCmd.bin, backendCmd.args, {\n cwd: wtCtx.workDir,\n env: backendEnv,\n stdio: ['ignore', 'pipe', 'pipe'],\n detached: false,\n });\n\n backend.stdout?.on('data', (data: Buffer) => {\n logger.debug(`[BE #${wtCtx.issueIid}] ${data.toString().trimEnd()}`);\n });\n backend.stderr?.on('data', (data: Buffer) => {\n logger.debug(`[BE #${wtCtx.issueIid} ERR] ${data.toString().trimEnd()}`);\n });\n backend.on('exit', (code) => {\n logger.info('Backend process exited', { issueIid: wtCtx.issueIid, code });\n });\n\n const frontendDir = path.join(wtCtx.workDir, 'frontend');\n const frontendEnv: Record<string, string> = {\n ...process.env as Record<string, string>,\n BACKEND_PORT: String(ports.backendPort),\n FRONTEND_PORT: String(ports.frontendPort),\n };\n\n const frontendCmd = this.options.frontendCommand\n ?? { bin: 'pnpm', args: ['dev', '--', '--port', String(ports.frontendPort)] };\n const frontend = spawn(frontendCmd.bin, frontendCmd.args, {\n cwd: frontendDir,\n env: frontendEnv,\n stdio: ['ignore', 'pipe', 'pipe'],\n detached: false,\n });\n\n frontend.stdout?.on('data', (data: Buffer) => {\n logger.debug(`[FE #${wtCtx.issueIid}] ${data.toString().trimEnd()}`);\n });\n frontend.stderr?.on('data', (data: Buffer) => {\n logger.debug(`[FE #${wtCtx.issueIid} ERR] ${data.toString().trimEnd()}`);\n });\n frontend.on('exit', (code) => {\n logger.info('Frontend process exited', { issueIid: wtCtx.issueIid, code });\n });\n\n const serverSet: ServerSet = {\n backend,\n frontend,\n ports,\n workDir: wtCtx.workDir,\n startedAt: new Date().toISOString(),\n };\n this.servers.set(wtCtx.issueIid, serverSet);\n\n logger.info('Waiting for servers to become healthy', { issueIid: wtCtx.issueIid });\n\n try {\n await Promise.all([\n waitForPort(\n ports.backendPort,\n false,\n this.options.healthCheckTimeoutMs,\n this.options.healthCheckIntervalMs,\n ),\n waitForPort(\n ports.frontendPort,\n true,\n this.options.healthCheckTimeoutMs,\n this.options.healthCheckIntervalMs,\n ),\n ]);\n logger.info('Dev servers healthy', { issueIid: wtCtx.issueIid, ...ports });\n } catch (err) {\n logger.error('Dev servers failed health check, cleaning up', {\n issueIid: wtCtx.issueIid,\n error: (err as Error).message,\n });\n this.stopServers(wtCtx.issueIid);\n throw err;\n }\n }\n\n stopServers(issueIid: number): void {\n const set = this.servers.get(issueIid);\n if (!set) return;\n\n logger.info('Stopping dev servers', { issueIid, ports: set.ports });\n\n killProcess(set.backend, `backend #${issueIid}`);\n killProcess(set.frontend, `frontend #${issueIid}`);\n\n this.servers.delete(issueIid);\n }\n\n stopAll(): void {\n for (const [iid] of this.servers) {\n this.stopServers(iid);\n }\n }\n\n getStatus(issueIid: number): { running: boolean; ports?: PortPair; startedAt?: string } {\n const set = this.servers.get(issueIid);\n if (!set) return { running: false };\n return {\n running: true,\n ports: set.ports,\n startedAt: set.startedAt,\n };\n }\n\n getRunningIssues(): number[] {\n return [...this.servers.keys()];\n }\n}\n\nfunction killProcess(proc: ChildProcess, label: string): void {\n try {\n if (proc.killed || proc.exitCode !== null) return;\n proc.kill('SIGTERM');\n setTimeout(() => {\n if (!proc.killed && proc.exitCode === null) {\n logger.warn(`Force killing ${label}`);\n proc.kill('SIGKILL');\n }\n }, 5_000);\n } catch (err) {\n logger.warn(`Failed to kill ${label}`, { error: (err as Error).message });\n }\n}\n","import type { Config } from '../config.js';\nimport type { IssueTracker } from '../tracker/IssueTracker.js';\n\nlet e2eOverride: boolean | undefined;\n\nexport function getE2eEnabled(cfg: Config): boolean {\n return e2eOverride ?? cfg.e2e.enabled;\n}\n\nexport function setE2eOverride(value: boolean | undefined): void {\n e2eOverride = value;\n}\n\nexport function isE2eEnabledForIssue(\n issueIid: number,\n tracker: IssueTracker,\n cfg: Config,\n): boolean {\n const record = tracker.get(issueIid);\n if (record?.e2eEnabled !== undefined) return record.e2eEnabled;\n return getE2eEnabled(cfg);\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport { logger as rootLogger } from '../logger.js';\n\nconst logger = rootLogger.child('ScreenshotCollector');\n\nconst MAX_SCREENSHOTS = 20;\n\nexport interface ScreenshotFile {\n filePath: string;\n testName: string;\n}\n\nfunction walkDir(dir: string, files: string[] = []): string[] {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const full = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walkDir(full, files);\n } else if (entry.isFile() && entry.name.endsWith('.png')) {\n files.push(full);\n }\n }\n return files;\n}\n\n/**\n * 从 worktree 的 frontend/test-results/ 目录收集 E2E 截图。\n * Playwright 以 `screenshot: 'on'` 运行时,每个测试的截图保存在\n * `test-results/<project>-<test-name>-<browser>/` 子目录下。\n */\nexport function collectScreenshots(workDir: string): ScreenshotFile[] {\n const testResultsDir = path.join(workDir, 'frontend', 'test-results');\n if (!fs.existsSync(testResultsDir)) {\n logger.debug('test-results directory not found', { dir: testResultsDir });\n return [];\n }\n\n const pngFiles = walkDir(testResultsDir);\n if (pngFiles.length === 0) {\n logger.debug('No screenshots found');\n return [];\n }\n\n const screenshots: ScreenshotFile[] = pngFiles.map((filePath) => {\n const relative = path.relative(testResultsDir, filePath);\n const testName = relative.split(path.sep)[0] || path.basename(filePath, '.png');\n return { filePath, testName };\n });\n\n if (screenshots.length > MAX_SCREENSHOTS) {\n logger.warn('Too many screenshots, truncating', {\n total: screenshots.length,\n max: MAX_SCREENSHOTS,\n });\n return screenshots.slice(0, MAX_SCREENSHOTS);\n }\n\n logger.info('Screenshots collected', { count: screenshots.length });\n return screenshots;\n}\n","import { GongfengClient, UploadResult } from '../clients/GongfengClient.js';\nimport { collectScreenshots, ScreenshotFile } from './ScreenshotCollector.js';\nimport { logger as rootLogger } from '../logger.js';\nimport { t } from '../i18n/index.js';\n\nconst logger = rootLogger.child('ScreenshotPublisher');\n\nexport interface PublishOptions {\n workDir: string;\n issueIid: number;\n issueId: number;\n mrIid?: number;\n}\n\ninterface UploadedScreenshot {\n testName: string;\n markdown: string;\n}\n\nfunction buildComment(uploaded: UploadedScreenshot[], truncated: boolean): string {\n const lines: string[] = [t('screenshot.title'), ''];\n\n for (const item of uploaded) {\n lines.push(`### ${item.testName}`, '', item.markdown, '');\n }\n\n if (truncated) {\n lines.push(t('screenshot.truncated'), '');\n }\n\n return lines.join('\\n');\n}\n\nexport class ScreenshotPublisher {\n constructor(private gongfeng: GongfengClient) {}\n\n async publish(options: PublishOptions): Promise<void> {\n const { workDir, issueIid, issueId, mrIid } = options;\n\n const screenshots = collectScreenshots(workDir);\n if (screenshots.length === 0) {\n logger.info('No E2E screenshots to publish', { issueIid });\n return;\n }\n\n const uploaded = await this.uploadAll(screenshots);\n if (uploaded.length === 0) {\n logger.warn('All screenshot uploads failed', { issueIid });\n return;\n }\n\n const truncated = screenshots.length >= 20;\n const comment = buildComment(uploaded, truncated);\n\n await this.postToIssue(issueId, comment);\n\n if (mrIid) {\n await this.postToMergeRequest(mrIid, comment);\n }\n\n logger.info('E2E screenshots published', {\n issueIid,\n mrIid,\n count: uploaded.length,\n });\n }\n\n private async uploadAll(screenshots: ScreenshotFile[]): Promise<UploadedScreenshot[]> {\n const results: UploadedScreenshot[] = [];\n\n for (const screenshot of screenshots) {\n try {\n const result: UploadResult = await this.gongfeng.uploadFile(screenshot.filePath);\n results.push({\n testName: screenshot.testName,\n markdown: result.markdown,\n });\n } catch (err) {\n logger.warn('Failed to upload screenshot', {\n filePath: screenshot.filePath,\n error: (err as Error).message,\n });\n }\n }\n\n return results;\n }\n\n private async postToIssue(issueId: number, comment: string): Promise<void> {\n try {\n await this.gongfeng.createIssueNote(issueId, comment);\n } catch (err) {\n logger.warn('Failed to post screenshots to issue', {\n issueId,\n error: (err as Error).message,\n });\n }\n }\n\n private async postToMergeRequest(mrIid: number, comment: string): Promise<void> {\n try {\n await this.gongfeng.createMergeRequestNote(mrIid, comment);\n } catch (err) {\n logger.warn('Failed to post screenshots to merge request', {\n mrIid,\n error: (err as Error).message,\n });\n }\n }\n}\n","/**\n * Lightweight Prometheus-compatible metrics collector.\n *\n * Provides counters and histograms without external dependencies.\n * Expose via the `/metrics` endpoint in the Web server.\n */\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface MetricLabels {\n [key: string]: string;\n}\n\ninterface CounterEntry {\n type: 'counter';\n help: string;\n values: Map<string, number>;\n}\n\ninterface HistogramEntry {\n type: 'histogram';\n help: string;\n buckets: number[];\n /** key → { counts per bucket, sum, count } */\n values: Map<string, { bucketCounts: number[]; sum: number; count: number }>;\n}\n\ntype MetricEntry = CounterEntry | HistogramEntry;\n\n// ---------------------------------------------------------------------------\n// Label helpers\n// ---------------------------------------------------------------------------\n\nfunction labelsToKey(labels: MetricLabels): string {\n const pairs = Object.entries(labels).sort(([a], [b]) => a.localeCompare(b));\n if (pairs.length === 0) return '';\n return pairs.map(([k, v]) => `${k}=\"${v}\"`).join(',');\n}\n\nfunction keyToPromLabels(key: string): string {\n return key ? `{${key}}` : '';\n}\n\n// ---------------------------------------------------------------------------\n// Default histogram bucket boundaries\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_BUCKETS = [\n 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60, 120, 300, 600,\n];\n\n// ---------------------------------------------------------------------------\n// Collector\n// ---------------------------------------------------------------------------\n\nexport class MetricsCollector {\n private readonly metrics = new Map<string, MetricEntry>();\n\n // ── Counter ─────────────────────────────────────────────────────────\n\n /** Register a new counter. Idempotent if name already exists. */\n registerCounter(name: string, help: string): void {\n if (this.metrics.has(name)) return;\n this.metrics.set(name, { type: 'counter', help, values: new Map() });\n }\n\n /** Increment a counter by `delta` (default 1). */\n incCounter(name: string, labels: MetricLabels = {}, delta = 1): void {\n const entry = this.metrics.get(name);\n if (!entry || entry.type !== 'counter') return;\n const key = labelsToKey(labels);\n entry.values.set(key, (entry.values.get(key) ?? 0) + delta);\n }\n\n /** Read current value (for testing). */\n getCounter(name: string, labels: MetricLabels = {}): number {\n const entry = this.metrics.get(name);\n if (!entry || entry.type !== 'counter') return 0;\n return entry.values.get(labelsToKey(labels)) ?? 0;\n }\n\n // ── Histogram ───────────────────────────────────────────────────────\n\n /** Register a new histogram with optional custom buckets. */\n registerHistogram(name: string, help: string, buckets?: number[]): void {\n if (this.metrics.has(name)) return;\n const sortedBuckets = [...(buckets ?? DEFAULT_BUCKETS)].sort((a, b) => a - b);\n this.metrics.set(name, { type: 'histogram', help, buckets: sortedBuckets, values: new Map() });\n }\n\n /** Observe a value in a histogram. */\n observeHistogram(name: string, value: number, labels: MetricLabels = {}): void {\n const entry = this.metrics.get(name);\n if (!entry || entry.type !== 'histogram') return;\n const key = labelsToKey(labels);\n let data = entry.values.get(key);\n if (!data) {\n data = { bucketCounts: new Array(entry.buckets.length).fill(0), sum: 0, count: 0 };\n entry.values.set(key, data);\n }\n data.sum += value;\n data.count += 1;\n // Store in the smallest bucket that fits (non-cumulative)\n for (let i = 0; i < entry.buckets.length; i++) {\n if (value <= entry.buckets[i]) {\n data.bucketCounts[i] += 1;\n break;\n }\n }\n }\n\n // ── Timer helper ────────────────────────────────────────────────────\n\n /** Start a timer. Returns a function that, when called, observes the elapsed seconds. */\n startTimer(histogramName: string, labels: MetricLabels = {}): () => number {\n const start = performance.now();\n return () => {\n const elapsed = (performance.now() - start) / 1000;\n this.observeHistogram(histogramName, elapsed, labels);\n return elapsed;\n };\n }\n\n // ── Prometheus exposition ───────────────────────────────────────────\n\n /** Render all metrics in Prometheus text exposition format. */\n serialize(): string {\n const lines: string[] = [];\n\n for (const [name, entry] of this.metrics) {\n if (entry.type === 'counter') {\n lines.push(`# HELP ${name} ${entry.help}`);\n lines.push(`# TYPE ${name} counter`);\n for (const [key, value] of entry.values) {\n lines.push(`${name}${keyToPromLabels(key)} ${value}`);\n }\n } else if (entry.type === 'histogram') {\n lines.push(`# HELP ${name} ${entry.help}`);\n lines.push(`# TYPE ${name} histogram`);\n for (const [key, data] of entry.values) {\n const lblStr = key ? `,${key}` : '';\n let cumulative = 0;\n for (let i = 0; i < entry.buckets.length; i++) {\n cumulative += data.bucketCounts[i];\n lines.push(`${name}_bucket{le=\"${entry.buckets[i]}\"${lblStr}} ${cumulative}`);\n }\n lines.push(`${name}_bucket{le=\"+Inf\"${lblStr}} ${data.count}`);\n lines.push(`${name}_sum${keyToPromLabels(key)} ${data.sum}`);\n lines.push(`${name}_count${keyToPromLabels(key)} ${data.count}`);\n }\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n }\n\n /** Reset all metric values (for testing). */\n reset(): void {\n for (const entry of this.metrics.values()) {\n if (entry.type === 'counter') {\n entry.values.clear();\n } else if (entry.type === 'histogram') {\n entry.values.clear();\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Singleton + pre-registered metrics\n// ---------------------------------------------------------------------------\n\nexport const metrics = new MetricsCollector();\n\n// Issue processing\nmetrics.registerCounter('iaf_issues_total', 'Total number of issues processed');\nmetrics.registerCounter('iaf_issues_succeeded_total', 'Number of successfully completed issues');\nmetrics.registerCounter('iaf_issues_failed_total', 'Number of failed issues');\nmetrics.registerCounter('iaf_issues_retried_total', 'Number of issue retries');\n\n// Phase execution\nmetrics.registerCounter('iaf_phases_total', 'Total number of phase executions');\nmetrics.registerCounter('iaf_phases_failed_total', 'Number of failed phase executions');\nmetrics.registerHistogram('iaf_phase_duration_seconds', 'Duration of phase execution in seconds', [\n 1, 5, 10, 30, 60, 120, 300, 600, 900, 1800,\n]);\n\n// AI runner\nmetrics.registerCounter('iaf_ai_calls_total', 'Total AI runner invocations');\nmetrics.registerCounter('iaf_ai_errors_total', 'AI runner errors');\nmetrics.registerHistogram('iaf_ai_duration_seconds', 'AI runner call duration in seconds', [\n 1, 5, 10, 30, 60, 120, 300, 600, 900, 1800,\n]);\n\n// Gongfeng API\nmetrics.registerCounter('iaf_gongfeng_requests_total', 'Total Gongfeng API requests');\nmetrics.registerCounter('iaf_gongfeng_errors_total', 'Gongfeng API errors');\nmetrics.registerHistogram('iaf_gongfeng_request_duration_seconds', 'Gongfeng API request duration in seconds', [\n 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10,\n]);\n\n// Webhook\nmetrics.registerCounter('iaf_webhook_commands_total', 'Total webhook commands received');\n\n// Braindump\nmetrics.registerCounter('iaf_braindump_batches_total', 'Total braindump batches');\nmetrics.registerCounter('iaf_braindump_tasks_total', 'Total braindump tasks');\n","import { GitOperations } from '../../git/GitOperations.js';\nimport { PlanPersistence } from '../../persistence/PlanPersistence.js';\nimport { IssueState } from '../../tracker/IssueState.js';\nimport type { IssueProcessingContext, OrchestratorDeps, SetupResult } from '../IssueProcessingContext.js';\nimport { logger as rootLogger } from '../../logger.js';\nimport { t } from '../../i18n/index.js';\n\nconst logger = rootLogger.child('SetupStep');\n\n/**\n * 执行 Issue 处理的初始化步骤:\n * - 更新标签为 processing\n * - fetch + 创建 worktree(受 mutex 保护)\n * - 更新状态为 BranchCreated\n * - 安装依赖\n * - 初始化 PlanPersistence(ensureDir, writeIssueMeta, writeProgress)\n *\n * 注:开始/重试评论已由锁评论(IssueClaimer.tryClaim)承担,此处不再重复发布。\n */\nexport async function executeSetup(\n ctx: IssueProcessingContext,\n deps: OrchestratorDeps,\n): Promise<SetupResult> {\n const { issue, wtCtx, record, pipelineDef, branchName } = ctx;\n\n // 1. 更新标签\n try {\n await deps.gongfeng.updateIssueLabels(issue.id, [\n ...issue.labels.filter(l => !l.startsWith('auto-finish:')),\n 'auto-finish:processing',\n ]);\n } catch (err) {\n logger.warn('Failed to update issue labels', { error: (err as Error).message });\n }\n\n // 2. fetch + worktree(受 mutex 保护)\n await deps.mainGitMutex.runExclusive(async () => {\n deps.emitProgress(issue.iid, 'fetch', t('orchestrator.fetchProgress'));\n await deps.mainGit.fetch();\n deps.emitProgress(issue.iid, 'worktree', t('orchestrator.worktreeProgress'));\n await deps.ensureWorktree(wtCtx);\n });\n\n // 3. 更新状态为 BranchCreated\n if (record.state === IssueState.Pending) {\n deps.tracker.updateState(issue.iid, IssueState.BranchCreated);\n }\n\n // 4. 安装依赖\n deps.emitProgress(issue.iid, 'install', t('orchestrator.installProgress'));\n await deps.installDependencies(wtCtx.workDir);\n\n // 5. 初始化 PlanPersistence\n deps.emitProgress(issue.iid, 'init_plan', t('orchestrator.initPlanProgress'));\n const wtGit = new GitOperations(wtCtx.gitRootDir);\n const wtPlan = new PlanPersistence(wtCtx.workDir, issue.iid);\n\n wtPlan.ensureDir();\n wtPlan.writeIssueMeta({\n id: issue.id,\n iid: issue.iid,\n title: issue.title,\n labels: issue.labels,\n state: issue.state,\n });\n\n const existingProgress = wtPlan.readProgress();\n if (!existingProgress) {\n wtPlan.writeProgress(\n wtPlan.createInitialProgress(issue.iid, issue.title, branchName, pipelineDef),\n );\n }\n\n return { wtGit, wtPlan };\n}\n","import type { GitOperations } from '../../git/GitOperations.js';\nimport type { PlanPersistence } from '../../persistence/PlanPersistence.js';\nimport { ServiceShutdownError } from '../../errors/index.js';\nimport { AIExecutionError } from '../../errors/index.js';\nimport { isShuttingDown } from '../../shutdown/ShutdownSignal.js';\nimport { createPhase } from '../../phases/PhaseFactory.js';\nimport type { VerifyPhase, VerifyRunResult } from '../../phases/VerifyPhase.js';\nimport type { IssueProcessingContext, OrchestratorDeps, PhaseLoopResult } from '../IssueProcessingContext.js';\nimport { logger as rootLogger } from '../../logger.js';\nimport { t } from '../../i18n/index.js';\n\nconst logger = rootLogger.child('PhaseLoopStep');\n\n/**\n * 执行流水线阶段循环:\n * - 确定恢复阶段索引\n * - 逐个执行阶段\n * - 处理 gate 阶段(自动批准或等待审核)\n * - 执行 AI 阶段\n * - 按需启动预览服务器\n * - verify 阶段支持 verify-fix loop(验证失败自动回退 build 修复)\n *\n * 如果到达 gate 阶段且不自动批准,该函数 return 且 `paused` 为 true。\n */\nexport async function executePhaseLoop(\n ctx: IssueProcessingContext,\n deps: OrchestratorDeps,\n wtGit: GitOperations,\n wtPlan: PlanPersistence,\n): Promise<PhaseLoopResult & { paused: boolean }> {\n const { issue, pipelineDef, lifecycleManager, record, isRetry, phaseCtx } = ctx;\n\n const startIdx = lifecycleManager.determineResumePhaseIndex(\n record.state,\n isRetry ? record.failedAtState : undefined,\n record.currentPhase,\n );\n\n deps.emitProgress(\n issue.iid,\n 'phase_start',\n t('orchestrator.phaseStartProgress', {\n phase: pipelineDef.phases[startIdx]?.name ?? 'start',\n }),\n );\n\n const needsDeployment = deps.shouldDeployServers(issue.iid);\n let serversStarted = false;\n\n for (let i = startIdx; i < pipelineDef.phases.length; i++) {\n if (isShuttingDown()) {\n throw new ServiceShutdownError();\n }\n\n const spec = pipelineDef.phases[i];\n\n // ── Gate 阶段处理 ──\n if (spec.kind === 'gate') {\n if (deps.shouldAutoApprove(issue.labels)) {\n logger.info('Auto-approving review gate (matched autoApproveLabels)', {\n iid: issue.iid,\n labels: issue.labels,\n autoApproveLabels: deps.config.review.autoApproveLabels,\n });\n if (spec.approvedState) {\n deps.tracker.updateState(issue.iid, spec.approvedState, { currentPhase: spec.name });\n }\n wtPlan.updatePhaseProgress(spec.name, 'completed');\n try {\n await deps.gongfeng.createIssueNote(\n issue.id,\n t('orchestrator.autoApproveComment'),\n );\n } catch { /* ignore */ }\n continue;\n }\n\n // 暂停等待审核\n deps.tracker.updateState(issue.iid, spec.startState, { currentPhase: spec.name });\n wtPlan.updatePhaseProgress(spec.name, 'in_progress');\n deps.eventBus.emitTyped('review:requested', { issueIid: issue.iid });\n logger.info('Review gate reached, pausing', { iid: issue.iid });\n return { serversStarted, paused: true };\n }\n\n // ── Verify-Fix Loop ──\n if (spec.name === 'verify' && deps.config.verifyFixLoop.enabled) {\n // 找到 build 阶段索引(verify 的前一个 AI 阶段)\n const buildIdx = findPreviousAiPhaseIndex(pipelineDef.phases, i);\n await executeVerifyFixLoop(ctx, deps, wtGit, wtPlan, i, buildIdx);\n continue;\n }\n\n // ── AI 阶段执行 ──\n const hooks = deps.buildPhaseHooks(issue.iid, issue.id);\n const phase = createPhase(spec.name, deps.aiRunner, wtGit, wtPlan, deps.config, lifecycleManager, hooks);\n await phase.execute(phaseCtx);\n\n // ── 按需启动预览服务器 ──\n if (needsDeployment && !serversStarted && lifecycleManager.shouldDeployPreview(spec.name)) {\n const ports = await deps.startPreviewServers(ctx.wtCtx, issue);\n if (ports) {\n phaseCtx.ports = ports;\n ctx.wtCtx.ports = ports;\n serversStarted = true;\n }\n }\n }\n\n return { serversStarted, paused: false };\n}\n\n/**\n * 查找指定索引之前最近的 AI 阶段索引。\n * 用于 verify-fix loop 定位需要回退的 build 阶段。\n */\nfunction findPreviousAiPhaseIndex(\n phases: readonly { kind: string }[],\n currentIdx: number,\n): number {\n for (let j = currentIdx - 1; j >= 0; j--) {\n if (phases[j].kind === 'ai') return j;\n }\n return -1;\n}\n\n/**\n * 验证-修复循环:\n * 1. 执行 verify 阶段,解析报告\n * 2. 如果验证通过,结束\n * 3. 如果验证未通过且未达上限,回退执行 build 阶段(带修复上下文),然后重新验证\n * 4. 如果达到最大迭代次数仍未通过,抛出错误\n */\nasync function executeVerifyFixLoop(\n ctx: IssueProcessingContext,\n deps: OrchestratorDeps,\n wtGit: GitOperations,\n wtPlan: PlanPersistence,\n verifyPhaseIdx: number,\n buildPhaseIdx: number,\n): Promise<void> {\n const { issue, lifecycleManager, phaseCtx } = ctx;\n const maxIterations = deps.config.verifyFixLoop.maxIterations;\n\n deps.eventBus.emitTyped('verify:loopStarted', {\n issueIid: issue.iid,\n maxIterations,\n });\n\n logger.info('Verify-fix loop started', {\n iid: issue.iid,\n maxIterations,\n buildPhaseIdx,\n });\n\n for (let iteration = 1; iteration <= maxIterations; iteration++) {\n if (isShuttingDown()) {\n throw new ServiceShutdownError();\n }\n\n logger.info('Verify-fix loop iteration', {\n iteration,\n maxIterations,\n iid: issue.iid,\n });\n\n // ── 执行 verify 阶段 ──\n const verifyHooks = deps.buildPhaseHooks(issue.iid, issue.id);\n const verifyPhase = createPhase(\n 'verify', deps.aiRunner, wtGit, wtPlan, deps.config, lifecycleManager, verifyHooks,\n ) as VerifyPhase;\n\n let verifyResult: VerifyRunResult;\n try {\n verifyResult = await verifyPhase.execute(phaseCtx);\n } catch (err) {\n // AI 进程本身就失败了(exit code != 0)\n logger.warn('Verify phase execution failed', {\n iteration,\n iid: issue.iid,\n error: (err as Error).message,\n });\n\n deps.eventBus.emitTyped('verify:iterationComplete', {\n issueIid: issue.iid,\n iteration,\n passed: false,\n failures: ['AI runner execution failed'],\n });\n\n if (iteration === maxIterations) {\n throw err; // 最后一轮,传播原始错误\n }\n\n // 回退到 build 进行修复\n if (buildPhaseIdx >= 0) {\n await executeBuildFix(ctx, deps, wtGit, wtPlan, buildPhaseIdx, {\n iteration,\n verifyFailures: ['AI runner execution failed: ' + (err as Error).message],\n rawReport: '',\n });\n }\n continue;\n }\n\n // ── 检查验证报告结果 ──\n const report = verifyResult.verifyReport;\n const passed = report ? report.passed : true; // 无报告时视为通过\n\n deps.eventBus.emitTyped('verify:iterationComplete', {\n issueIid: issue.iid,\n iteration,\n passed,\n failures: report?.failureReasons,\n });\n\n if (passed) {\n logger.info('Verify-fix loop passed', {\n iteration,\n iid: issue.iid,\n });\n return; // 验证通过,循环结束\n }\n\n // ── 验证未通过 ──\n logger.info('Verify failed, issues found', {\n iteration,\n iid: issue.iid,\n failures: report?.failureReasons,\n todolistStats: report?.todolistStats,\n });\n\n if (iteration === maxIterations) {\n // 达到最大迭代次数\n deps.eventBus.emitTyped('verify:loopExhausted', {\n issueIid: issue.iid,\n totalIterations: iteration,\n failures: report?.failureReasons ?? [],\n });\n\n const failMsg = `Verify-fix loop exhausted after ${maxIterations} iterations. ` +\n `Remaining issues: ${report?.failureReasons?.join('; ') ?? 'unknown'}`;\n logger.warn(failMsg, { iid: issue.iid });\n\n throw new AIExecutionError('verify', failMsg, {\n output: report?.rawReport ?? '',\n exitCode: 0,\n });\n }\n\n // ── 回退到 build 阶段修复 ──\n if (buildPhaseIdx >= 0) {\n await executeBuildFix(ctx, deps, wtGit, wtPlan, buildPhaseIdx, {\n iteration,\n verifyFailures: report?.failureReasons ?? [],\n rawReport: report?.rawReport ?? '',\n });\n }\n }\n}\n\n/**\n * 在 verify-fix loop 中执行 build 阶段的修复迭代。\n * 将验证失败信息通过 fixContext 注入到 build prompt。\n */\nasync function executeBuildFix(\n ctx: IssueProcessingContext,\n deps: OrchestratorDeps,\n wtGit: GitOperations,\n wtPlan: PlanPersistence,\n buildPhaseIdx: number,\n fixContext: { iteration: number; verifyFailures: string[]; rawReport: string },\n): Promise<void> {\n const { issue, lifecycleManager, phaseCtx } = ctx;\n\n logger.info('Looping back to build for fix', {\n iteration: fixContext.iteration,\n iid: issue.iid,\n failures: fixContext.verifyFailures,\n });\n\n // 注入修复上下文\n phaseCtx.fixContext = fixContext;\n\n try {\n const buildHooks = deps.buildPhaseHooks(issue.iid, issue.id);\n const buildPhase = createPhase(\n 'build', deps.aiRunner, wtGit, wtPlan, deps.config, lifecycleManager, buildHooks,\n );\n await buildPhase.execute(phaseCtx);\n } finally {\n // 清除修复上下文\n delete phaseCtx.fixContext;\n }\n}\n","import { IssueState } from '../../tracker/IssueState.js';\nimport { isE2eEnabledForIssue } from '../../e2e/E2eSettings.js';\nimport { metrics } from '../../metrics/MetricsCollector.js';\nimport type { IssueProcessingContext, OrchestratorDeps, PhaseLoopResult } from '../IssueProcessingContext.js';\nimport { logger as rootLogger } from '../../logger.js';\nimport { t } from '../../i18n/index.js';\n\nconst logger = rootLogger.child('CompletionStep');\n\n/**\n * 执行 Issue 处理的完成步骤:\n * - 创建 MR\n * - 更新状态为 Completed\n * - 更新标签为 done\n * - 发布 E2E 截图\n * - 发布完成评论\n * - 释放锁评论\n * - 清理 worktree 或保留预览\n */\nexport async function executeCompletion(\n ctx: IssueProcessingContext,\n deps: OrchestratorDeps,\n phaseResult: PhaseLoopResult,\n): Promise<void> {\n const { issue, branchName, wtCtx } = ctx;\n\n // 1. 创建 MR\n deps.emitProgress(issue.iid, 'create_mr', t('orchestrator.createMrProgress'));\n const previewUrl = deps.buildPreviewUrl(issue.iid);\n const mrResult = await deps.tryCreateMergeRequest(issue, branchName, wtCtx.workDir, previewUrl);\n const mrUrl = mrResult?.url ?? null;\n\n // 2. 更新状态为 Completed\n deps.tracker.updateState(issue.iid, IssueState.Completed, mrUrl ? { mrUrl } : undefined);\n metrics.incCounter('iaf_issues_succeeded_total', { pipeline: ctx.pipelineDef.mode });\n\n // 3. 更新标签为 done\n try {\n await deps.gongfeng.updateIssueLabels(issue.id, [\n ...issue.labels.filter(l => !l.startsWith('auto-finish:') && l !== 'auto-finish'),\n 'auto-finish:done',\n ]);\n } catch {\n // ignore\n }\n\n // 4. 发布 E2E 截图\n if (isE2eEnabledForIssue(issue.iid, deps.tracker, deps.config)) {\n deps.emitProgress(issue.iid, 'screenshots', t('orchestrator.uploadScreenshotsProgress'));\n try {\n await deps.screenshotPublisher.publish({\n workDir: wtCtx.workDir,\n issueIid: issue.iid,\n issueId: issue.id,\n mrIid: mrResult?.iid,\n });\n } catch (err) {\n logger.warn('Failed to publish E2E screenshots', {\n iid: issue.iid,\n error: (err as Error).message,\n });\n }\n }\n\n // 5. 发布完成评论\n const mrSection = mrUrl\n ? t('orchestrator.mrSection', { mrUrl })\n : t('orchestrator.mrFailSection');\n const previewSection = previewUrl ? `\\n🌐 Preview: ${previewUrl}` : '';\n try {\n await deps.gongfeng.createIssueNote(\n issue.id,\n t('orchestrator.completedComment', { branch: branchName, mrSection, previewSection }),\n );\n } catch {\n // ignore\n }\n\n // 6. 释放锁评论(多节点协调)\n if (deps.claimer) {\n await deps.claimer.releaseClaim(issue.id, issue.iid, 'completed');\n }\n\n // 7. 清理 worktree 或保留预览\n if (phaseResult.serversStarted && deps.config.preview.keepAfterComplete) {\n logger.info('Preview servers kept running after completion', { iid: issue.iid });\n } else {\n deps.stopPreviewServers(issue.iid);\n await deps.mainGitMutex.runExclusive(async () => {\n try {\n await deps.mainGit.worktreeRemove(wtCtx.gitRootDir, true);\n logger.info('Worktree cleaned up', { dir: wtCtx.gitRootDir });\n } catch (err) {\n logger.warn('Failed to cleanup worktree', {\n dir: wtCtx.gitRootDir,\n error: (err as Error).message,\n });\n }\n });\n }\n\n logger.info('Issue processing completed', { iid: issue.iid });\n}\n","import { IssueState } from '../../tracker/IssueState.js';\nimport type { GongfengIssue } from '../../clients/GongfengClient.js';\nimport type { WorktreeContext } from '../../git/WorktreeContext.js';\nimport { metrics } from '../../metrics/MetricsCollector.js';\nimport type { OrchestratorDeps } from '../IssueProcessingContext.js';\nimport { logger as rootLogger } from '../../logger.js';\nimport { t } from '../../i18n/index.js';\n\nconst logger = rootLogger.child('FailureHandler');\n\n/**\n * 处理 Issue 处理失败:\n * - 在 tracker 中标记失败\n * - 更新标签为 failed\n * - 发布失败评论\n * - 释放锁评论\n * - 处理\"处理中被重置\"的边缘情况\n */\nexport async function handleFailure(\n err: unknown,\n issue: GongfengIssue,\n wtCtx: WorktreeContext,\n deps: OrchestratorDeps,\n): Promise<void> {\n const errorMsg = (err as Error).message;\n logger.error('Issue processing failed', { iid: issue.iid, error: errorMsg });\n metrics.incCounter('iaf_issues_failed_total');\n\n // 1. 标记失败(检测重置边缘情况)\n const currentRecord = deps.tracker.get(issue.iid);\n const failedAtState = currentRecord?.state || IssueState.Pending;\n const wasReset = failedAtState === IssueState.Pending && currentRecord?.attempts === 0;\n\n if (failedAtState !== IssueState.Failed && !wasReset) {\n deps.tracker.markFailed(issue.iid, errorMsg.slice(0, 500), failedAtState);\n }\n\n if (wasReset) {\n logger.info('Issue was reset during processing, skipping failure marking', { iid: issue.iid });\n throw err;\n }\n\n // 2. 更新标签为 failed\n try {\n await deps.gongfeng.updateIssueLabels(issue.id, [\n ...issue.labels.filter(l => !l.startsWith('auto-finish:') && l !== 'auto-finish'),\n 'auto-finish', 'auto-finish:failed',\n ]);\n } catch {\n // ignore\n }\n\n // 3. 发布失败评论\n try {\n await deps.gongfeng.createIssueNote(\n issue.id,\n t('orchestrator.failedComment', { error: errorMsg }),\n );\n } catch {\n // ignore\n }\n\n // 4. 释放锁评论\n if (deps.claimer) {\n try {\n await deps.claimer.releaseClaim(issue.id, issue.iid, 'failed');\n } catch (releaseErr) {\n logger.warn('Failed to release lock on failure', {\n iid: issue.iid,\n error: (releaseErr as Error).message,\n });\n }\n }\n\n logger.info('Worktree preserved for debugging', { dir: wtCtx.gitRootDir });\n throw err;\n}\n","import { randomUUID } from 'node:crypto';\nimport { logger as rootLogger } from '../logger.js';\nimport type { AIRunner, RunResult, StreamEvent } from '../ai-runner/AIRunner.js';\nimport { createAIRunner, type AIConfig } from '../ai-runner/index.js';\nimport type { BrainstormAgentConfig, Config } from '../config.js';\nimport {\n buildGeneratePrompt,\n buildReviewPrompt,\n buildRefinePrompt,\n} from '../prompts/brainstorm-templates.js';\n\nconst logger = rootLogger.child('Brainstorm');\n\nexport interface BrainstormRound {\n round: number;\n questions: string;\n refinedSdd: string;\n}\n\nexport type BrainstormStatus =\n | 'idle'\n | 'generating'\n | 'reviewing'\n | 'refining'\n | 'done'\n | 'error';\n\nexport interface BrainstormSession {\n id: string;\n transcript: string;\n currentSdd: string;\n rounds: BrainstormRound[];\n status: BrainstormStatus;\n error?: string;\n generatorSessionId?: string;\n createdAt: string;\n}\n\nexport interface BrainstormStreamEvent {\n type: 'sdd:chunk' | 'sdd:complete' | 'review:chunk' | 'review:complete'\n | 'round:start' | 'round:complete' | 'error';\n data: unknown;\n round?: number;\n}\n\nfunction agentConfigToAIConfig(\n agentCfg: BrainstormAgentConfig,\n timeoutMs: number,\n): AIConfig {\n return {\n mode: agentCfg.mode,\n binary: agentCfg.binary,\n phaseTimeoutMs: timeoutMs,\n nvmNodeVersion: agentCfg.nvmNodeVersion,\n model: agentCfg.model,\n };\n}\n\nexport class BrainstormService {\n private sessions = new Map<string, BrainstormSession>();\n private generatorRunner: AIRunner;\n private reviewerRunner: AIRunner;\n private config: Config['brainstorm'];\n private workDir: string;\n\n constructor(config: Config) {\n this.config = config.brainstorm;\n this.workDir = config.project.workDir;\n this.generatorRunner = createAIRunner(\n agentConfigToAIConfig(this.config.generator, this.config.timeoutMs),\n );\n this.reviewerRunner = createAIRunner(\n agentConfigToAIConfig(this.config.reviewer, this.config.timeoutMs),\n );\n }\n\n createSession(transcript: string): BrainstormSession {\n const session: BrainstormSession = {\n id: randomUUID(),\n transcript,\n currentSdd: '',\n rounds: [],\n status: 'idle',\n createdAt: new Date().toISOString(),\n };\n this.sessions.set(session.id, session);\n logger.info('Created brainstorm session', { sessionId: session.id });\n return session;\n }\n\n getSession(id: string): BrainstormSession | undefined {\n return this.sessions.get(id);\n }\n\n async generate(\n sessionId: string,\n onEvent?: (event: BrainstormStreamEvent) => void,\n ): Promise<RunResult> {\n const session = this.requireSession(sessionId);\n session.status = 'generating';\n logger.info('Generating SDD', { sessionId });\n\n const prompt = buildGeneratePrompt(session.transcript);\n const result = await this.generatorRunner.run({\n prompt,\n workDir: this.workDir,\n timeoutMs: this.config.timeoutMs,\n onStreamEvent: (evt: StreamEvent) => {\n onEvent?.({ type: 'sdd:chunk', data: evt });\n },\n });\n\n if (result.success) {\n session.currentSdd = result.output;\n session.generatorSessionId = result.sessionId;\n session.status = 'idle';\n onEvent?.({ type: 'sdd:complete', data: { sdd: result.output } });\n } else {\n session.status = 'error';\n session.error = result.output;\n onEvent?.({ type: 'error', data: { message: result.output } });\n }\n\n return result;\n }\n\n async review(\n sessionId: string,\n onEvent?: (event: BrainstormStreamEvent) => void,\n ): Promise<RunResult> {\n const session = this.requireSession(sessionId);\n const roundNum = session.rounds.length + 1;\n session.status = 'reviewing';\n logger.info('Reviewing SDD', { sessionId, round: roundNum });\n onEvent?.({ type: 'round:start', data: { round: roundNum, phase: 'review' }, round: roundNum });\n\n const prompt = buildReviewPrompt(session.currentSdd, roundNum);\n const result = await this.reviewerRunner.run({\n prompt,\n workDir: this.workDir,\n timeoutMs: this.config.timeoutMs,\n onStreamEvent: (evt: StreamEvent) => {\n onEvent?.({ type: 'review:chunk', data: evt, round: roundNum });\n },\n });\n\n if (result.success) {\n session.rounds.push({\n round: roundNum,\n questions: result.output,\n refinedSdd: '',\n });\n session.status = 'idle';\n onEvent?.({ type: 'review:complete', data: { round: roundNum, questions: result.output }, round: roundNum });\n } else {\n session.status = 'error';\n session.error = result.output;\n onEvent?.({ type: 'error', data: { message: result.output, round: roundNum }, round: roundNum });\n }\n\n return result;\n }\n\n async refine(\n sessionId: string,\n onEvent?: (event: BrainstormStreamEvent) => void,\n ): Promise<RunResult> {\n const session = this.requireSession(sessionId);\n const currentRound = session.rounds[session.rounds.length - 1];\n if (!currentRound) {\n throw new Error('No review round to refine from');\n }\n\n session.status = 'refining';\n logger.info('Refining SDD', { sessionId, round: currentRound.round });\n\n const prompt = buildRefinePrompt(currentRound.questions);\n const result = await this.generatorRunner.run({\n prompt,\n workDir: this.workDir,\n timeoutMs: this.config.timeoutMs,\n sessionId: session.generatorSessionId,\n continueSession: !!session.generatorSessionId,\n onStreamEvent: (evt: StreamEvent) => {\n onEvent?.({ type: 'sdd:chunk', data: evt, round: currentRound.round });\n },\n });\n\n if (result.success) {\n currentRound.refinedSdd = result.output;\n session.currentSdd = result.output;\n session.generatorSessionId = result.sessionId ?? session.generatorSessionId;\n session.status = 'idle';\n onEvent?.({\n type: 'round:complete',\n data: { round: currentRound.round, sdd: result.output },\n round: currentRound.round,\n });\n } else {\n session.status = 'error';\n session.error = result.output;\n onEvent?.({ type: 'error', data: { message: result.output, round: currentRound.round }, round: currentRound.round });\n }\n\n return result;\n }\n\n async autoRefine(\n sessionId: string,\n rounds?: number,\n onEvent?: (event: BrainstormStreamEvent) => void,\n ): Promise<void> {\n const maxRounds = Math.min(rounds ?? this.config.maxRefinementRounds, this.config.maxRefinementRounds);\n const session = this.requireSession(sessionId);\n\n if (!session.currentSdd) {\n await this.generate(sessionId, onEvent);\n if (session.status === 'error') return;\n }\n\n for (let i = 0; i < maxRounds; i++) {\n const reviewResult = await this.review(sessionId, onEvent);\n if (!reviewResult.success) break;\n\n const refineResult = await this.refine(sessionId, onEvent);\n if (!refineResult.success) break;\n }\n\n if (session.status !== 'error') {\n session.status = 'done';\n }\n }\n\n private requireSession(id: string): BrainstormSession {\n const session = this.sessions.get(id);\n if (!session) {\n throw new Error(`Brainstorm session not found: ${id}`);\n }\n return session;\n }\n}\n","export function buildGeneratePrompt(transcript: string): string {\n return `你是一个资深软件架构师。下面是用户通过语音倾倒的一段关于软件需求的想法,内容可能不连贯、有重复、夹杂语气词——这是正常的。\n\n**核心原则——第一性原理思考:**\n- 不要假设用户非常清楚自己想要什么以及该怎么得到。用户往往只有模糊的意图,你的工作是从原始需求和底层问题出发,帮他厘清真正的目标。\n- 如果用户的动机和目标不清晰,在 SDD 中明确标注 [待澄清],说明为什么这里需要进一步讨论,并给出你的理解和建议。\n- 如果目标清晰但用户描述的路径不是最优解,指出来,并建议更好的方案。用 [更优路径] 标注这类建议。\n- 回到问题的本质:先问\"用户真正要解决的问题是什么\",再想\"最简单有效的方案是什么\",避免过度设计。\n\n请你:\n1. 首先使用 Read、Grep、Glob 等工具浏览项目代码库,了解现有架构、技术栈和代码风格\n2. 分析用户想法的底层动机——他要解决什么问题?为什么要解决?现有方案为什么不够?\n3. 基于对代码库的理解和用户的真实需求,生成一份结构化的软件设计文档 (SDD)\n\nSDD 输出要求:\n- 使用 Markdown 格式\n- 包含以下章节:概述、目标与范围、技术方案(含架构设计、数据模型、接口设计)、实施计划、风险与约束\n- 在\"概述\"章节中,先用 2-3 句话阐明你理解的用户核心诉求和底层动机,再展开方案\n- 结合项目现有代码结构给出具体的文件路径和模块建议\n- 如果用户的想法中有模糊或矛盾的地方,先做合理推断并标注 [推断]\n- 如果发现更短的实现路径或更简洁的方案,用 [更优路径] 标注并说明理由\n\n用户的想法原文:\n---\n${transcript}\n---\n\n请直接输出完整的 SDD 文档内容(纯 Markdown 文本),不要输出任何多余解释。`;\n}\n\nexport function buildReviewPrompt(sdd: string, round: number): string {\n return `你是一个严谨的技术评审专家。请你仔细审查以下软件设计文档 (SDD)。\n\n请你:\n1. 使用 Read、Grep、Glob 等工具浏览项目代码库,验证 SDD 中提到的模块、路径、接口是否与现有代码一致\n2. 用第一性原理审视:需求本身是否合理?目标是否清晰?是否存在更简单直接的实现路径被忽略了?\n3. 站在实际实施者的角度,找出文档中**未说清楚、含糊不清、缺失、或可能导致实施困难**的地方\n4. 列出恰好 20 个问题,按严重程度排序(最重要的在前)\n\n这是第 ${round} 轮审查${round > 1 ? ',请关注比之前更细粒度的问题,特别是边界条件、错误处理、性能、安全等方面' : ''}。\n\nSDD 文档:\n---\n${sdd}\n---\n\n输出格式要求:\n每个问题用编号列出,格式为:\n1. [类别] 问题描述\n\n类别包括:[缺失]、[模糊]、[矛盾]、[风险]、[建议]、[动机](需求动机或目标本身需要质疑时)、[过度设计](存在更简单路径时)\n\n请直接输出 20 个问题,不要输出多余解释。`;\n}\n\nexport function buildRefinePrompt(questions: string): string {\n return `一位技术评审专家审查了你之前生成的 SDD,发现了以下问题:\n\n${questions}\n\n请你:\n1. 逐一回应每个问题,在 SDD 中修复或补充对应内容\n2. 如果某个问题需要查看代码来回答,请使用 Read、Grep、Glob 等工具查看项目代码后再作答\n3. 对无法确定的问题,给出多种方案并标注推荐方案\n\n请输出修复后的完整 SDD 文档(纯 Markdown 文本),不要输出对比说明,直接给出最新版本。`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;;;ACCjB,IAAMA,UAAS,OAAW,MAAM,gBAAgB;AAiBzC,IAAM,iBAAN,MAAqB;AAAA,EAS1B,YACmB,MACjB,SACA;AAFiB;AAGjB,SAAK,mBAAmB,SAAS,oBAAoB;AACrD,SAAK,iBAAiB,SAAS,kBAAkB;AACjD,SAAK,mBAAmB,SAAS,oBAAoB;AAAA,EACvD;AAAA,EAfQ,QAAsB;AAAA,EACtB,eAAe;AAAA,EACf,eAAe;AAAA,EACf,kBAAkB;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EAWjB,WAAyB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,QAAW,IAAkC;AACjD,QAAI,KAAK,UAAU,mBAAmB;AACpC,UAAI,KAAK,IAAI,IAAI,KAAK,mBAAmB,KAAK,gBAAgB;AAC5D,aAAK,aAAa,0BAAqB;AAAA,MACzC,OAAO;AACL,cAAM,IAAI,MAAM,oBAAoB,KAAK,IAAI,WAAW;AAAA,MAC1D;AAAA,IACF;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,GAAG;AACxB,WAAK,UAAU;AACf,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,WAAK,UAAU;AACf,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA,EAGA,QAAc;AACZ,SAAK,eAAe;AACpB,SAAK,eAAe;AACpB,SAAK,kBAAkB;AACvB,SAAK,aAAa,qBAAmB;AAAA,EACvC;AAAA,EAEQ,YAAkB;AACxB,QAAI,KAAK,UAAU,4BAAuB;AACxC,WAAK;AACL,UAAI,KAAK,gBAAgB,KAAK,kBAAkB;AAC9C,aAAK,aAAa,qBAAmB;AAAA,MACvC;AAAA,IACF,OAAO;AAEL,WAAK,eAAe;AAAA,IACtB;AAAA,EACF;AAAA,EAEQ,YAAkB;AACxB,SAAK;AACL,SAAK,kBAAkB,KAAK,IAAI;AAEhC,QAAI,KAAK,UAAU,4BAAuB;AAExC,WAAK,aAAa,iBAAiB;AAAA,IACrC,WAAW,KAAK,gBAAgB,KAAK,kBAAkB;AACrD,WAAK,aAAa,iBAAiB;AAAA,IACrC;AAAA,EACF;AAAA,EAEQ,aAAa,UAA8B;AACjD,QAAI,KAAK,UAAU,SAAU;AAC7B,UAAM,WAAW,KAAK;AACtB,SAAK,QAAQ;AAEb,QAAI,aAAa,uBAAqB;AACpC,WAAK,eAAe;AACpB,WAAK,eAAe;AAAA,IACtB,WAAW,aAAa,4BAAuB;AAC7C,WAAK,eAAe;AAAA,IACtB;AAEA,IAAAC,QAAO,KAAK,oCAAoC;AAAA,MAC9C,MAAM,KAAK;AAAA,MACX,MAAM;AAAA,MACN,IAAI;AAAA,IACN,CAAC;AAAA,EACH;AACF;;;AC5GA,IAAMC,UAAS,OAAW,MAAM,aAAa;AAetC,IAAM,cAAN,MAAkB;AAAA,EACN;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEjB,YAAY,SAA8B;AACxC,SAAK,aAAa,SAAS,cAAc;AACzC,SAAK,cAAc,SAAS,eAAe;AAC3C,SAAK,aAAa,SAAS,cAAc;AACzC,SAAK,eAAe,SAAS,gBAAgB;AAC7C,SAAK,cAAc,SAAS,gBAAgB,MAAM;AAAA,EACpD;AAAA;AAAA,EAGA,MAAM,QAAW,IAAsB,SAA8B;AACnE,QAAI;AACJ,aAAS,UAAU,GAAG,WAAW,KAAK,YAAY,WAAW;AAC3D,UAAI;AACF,eAAO,MAAM,GAAG;AAAA,MAClB,SAAS,KAAK;AACZ,oBAAY;AACZ,YAAI,WAAW,KAAK,cAAc,CAAC,KAAK,YAAY,GAAG,GAAG;AACxD,gBAAM;AAAA,QACR;AACA,cAAM,QAAQ,KAAK,eAAe,OAAO;AACzC,QAAAA,QAAO,KAAK,wBAAwB;AAAA,UAClC;AAAA,UACA,SAAS,UAAU;AAAA,UACnB,YAAY,KAAK;AAAA,UACjB,SAAS;AAAA,UACT,OAAQ,IAAc;AAAA,QACxB,CAAC;AACD,cAAM,KAAK,MAAM,KAAK;AAAA,MACxB;AAAA,IACF;AACA,UAAM;AAAA,EACR;AAAA,EAEQ,eAAe,SAAyB;AAE9C,UAAM,cAAc,KAAK,cAAc,KAAK,IAAI,GAAG,OAAO;AAC1D,UAAM,SAAS,KAAK,IAAI,aAAa,KAAK,UAAU;AAEpD,UAAM,SAAS,SAAS,KAAK,gBAAgB,KAAK,OAAO,IAAI,IAAI;AACjE,WAAO,KAAK,IAAI,GAAG,KAAK,MAAM,SAAS,MAAM,CAAC;AAAA,EAChD;AAAA,EAEQ,MAAM,IAA2B;AACvC,WAAO,IAAI,QAAQ,aAAW,WAAW,SAAS,EAAE,CAAC;AAAA,EACvD;AACF;;;AF9DA,IAAMC,UAAS,OAAW,MAAM,gBAAgB;AAgEzC,IAAM,oBAAoB;AACjC,IAAM,4BAA4B;AAE3B,IAAM,iBAAN,MAAqB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACS;AAAA,EACA;AAAA,EAEjB,YAAY,QAAwB;AAClC,SAAK,SAAS,OAAO,OAAO,QAAQ,OAAO,EAAE;AAC7C,SAAK,QAAQ,OAAO;AACpB,SAAK,cAAc,OAAO;AAE1B,SAAK,cAAc,IAAI,YAAY;AAAA,MACjC,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,aAAa,CAAC,QAAiB;AAC7B,YAAI,eAAe,kBAAkB;AACnC,iBAAO,IAAI;AAAA,QACb;AAEA,YAAI,eAAe,cAAc,IAAI,QAAQ,SAAS,OAAO,KAAK,IAAI,QAAQ,SAAS,SAAS,IAAI;AAClG,iBAAO;AAAA,QACT;AACA,eAAO;AAAA,MACT;AAAA,IACF,CAAC;AAED,SAAK,iBAAiB,IAAI,eAAe,eAAe;AAAA,MACtD,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,MAChB,kBAAkB;AAAA,IACpB,CAAC;AAAA,EACH;AAAA,EAEA,IAAY,iBAAyB;AACnC,UAAM,UAAU,mBAAmB,KAAK,WAAW;AACnD,WAAO,GAAG,KAAK,MAAM,oBAAoB,OAAO;AAAA,EAClD;AAAA,EAEA,MAAc,WAAWC,QAAc,UAAuB,CAAC,GAAsB;AACnF,UAAM,MAAM,GAAG,KAAK,cAAc,GAAGA,MAAI;AACzC,IAAAD,QAAO,MAAM,eAAe,EAAE,QAAQ,QAAQ,UAAU,OAAO,IAAI,CAAC;AAEpE,WAAO,KAAK,eAAe;AAAA,MAAQ,MACjC,KAAK,YAAY,QAAQ,YAAY;AACnC,cAAM,OAAO,MAAM,MAAM,KAAK;AAAA,UAC5B,GAAG;AAAA,UACH,SAAS;AAAA,YACP,iBAAiB,KAAK;AAAA,YACtB,gBAAgB;AAAA,YAChB,GAAG,QAAQ;AAAA,UACb;AAAA,QACF,CAAC;AAED,YAAI,CAAC,KAAK,IAAI;AACZ,gBAAM,OAAO,MAAM,KAAK,KAAK;AAC7B,gBAAM,IAAI,iBAAiB,KAAK,QAAQ,sBAAsB,KAAK,MAAM,KAAK,IAAI,IAAI,IAAI;AAAA,QAC5F;AAEA,eAAO;AAAA,MACT,GAAG,cAAc,QAAQ,UAAU,KAAK,IAAIC,MAAI,EAAE;AAAA,IACpD;AAAA,EACF;AAAA,EAEA,MAAc,QAAWA,QAAc,UAAuB,CAAC,GAAe;AAC5E,UAAM,OAAO,MAAM,KAAK,WAAWA,QAAM,OAAO;AAChD,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EAEA,MAAM,YACJ,OACA,aACA,QACwB;AACxB,UAAM,OAA+B,EAAE,OAAO,YAAY;AAC1D,QAAI,UAAU,OAAO,SAAS,GAAG;AAC/B,WAAK,SAAS,OAAO,KAAK,GAAG;AAAA,IAC/B;AACA,UAAM,QAAQ,MAAM,KAAK,QAAuB,WAAW;AAAA,MACzD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,IAAI;AAAA,IAC3B,CAAC;AACD,IAAAD,QAAO,KAAK,iBAAiB,EAAE,IAAI,MAAM,IAAI,KAAK,MAAM,KAAK,MAAM,CAAC;AACpE,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WAAW,QAAgB,UAAU,QAA2C;AACpF,UAAM,SAAS,IAAI,gBAAgB,EAAE,OAAO,UAAU,MAAM,CAAC;AAC7D,QAAI,QAAQ;AACV,aAAO,IAAI,UAAU,MAAM;AAAA,IAC7B;AACA,WAAO,KAAK,QAAyB,WAAW,OAAO,SAAS,CAAC,EAAE;AAAA,EACrE;AAAA,EAEA,MAAM,mBAAmB,UAMrB,CAAC,GAAwD;AAC3D,UAAM,SAAS,IAAI,gBAAgB;AAAA,MACjC,OAAO,QAAQ,SAAS;AAAA,MACxB,MAAM,OAAO,QAAQ,QAAQ,CAAC;AAAA,MAC9B,UAAU,OAAO,QAAQ,WAAW,EAAE;AAAA,IACxC,CAAC;AACD,QAAI,QAAQ,QAAQ;AAClB,aAAO,IAAI,UAAU,QAAQ,MAAM;AAAA,IACrC;AACA,QAAI,QAAQ,QAAQ;AAClB,aAAO,IAAI,UAAU,QAAQ,MAAM;AAAA,IACrC;AACA,UAAM,OAAO,MAAM,KAAK,WAAW,WAAW,OAAO,SAAS,CAAC,EAAE;AACjE,UAAM,QAAQ,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,KAAK,EAAE;AAC7D,UAAM,SAAU,MAAM,KAAK,KAAK;AAChC,WAAO,EAAE,QAAQ,OAAO,SAAS,OAAO,OAAO;AAAA,EACjD;AAAA,EAEA,MAAM,eAAe,SAAyC;AAC5D,WAAO,KAAK,QAAuB,WAAW,OAAO,EAAE;AAAA,EACzD;AAAA,EAEA,MAAM,gBAAgB,SAAiB,MAA6B;AAClE,UAAM,aAAa,OAAO;AAC1B,UAAM,KAAK,QAAQ,WAAW,OAAO,UAAU;AAAA,MAC7C,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAAA,IAC3C,CAAC;AACD,IAAAA,QAAO,KAAK,sBAAsB,EAAE,QAAQ,CAAC;AAAA,EAC/C;AAAA,EAEA,MAAM,kBAAkB,SAAiB,QAAiC;AACxE,UAAM,KAAK,QAAQ,WAAW,OAAO,IAAI;AAAA,MACvC,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,QAAQ,OAAO,KAAK,GAAG,EAAE,CAAC;AAAA,IACnD,CAAC;AACD,IAAAA,QAAO,KAAK,wBAAwB,EAAE,SAAS,OAAO,CAAC;AAAA,EACzD;AAAA,EAEA,MAAM,mBAAmB,SAAmE;AAC1F,UAAM,KAAK,MAAM,KAAK,QAA8B,mBAAmB;AAAA,MACrE,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU;AAAA,QACnB,eAAe,QAAQ;AAAA,QACvB,eAAe,QAAQ;AAAA,QACvB,OAAO,QAAQ;AAAA,QACf,aAAa,QAAQ,eAAe;AAAA,MACtC,CAAC;AAAA,IACH,CAAC;AACD,QAAI,CAAC,GAAG,WAAW,GAAG,KAAK;AACzB,SAAG,UAAU,KAAK,qBAAqB,GAAG,GAAG;AAAA,IAC/C;AACA,IAAAA,QAAO,KAAK,yBAAyB,EAAE,KAAK,GAAG,KAAK,QAAQ,GAAG,QAAQ,CAAC;AACxE,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,yBACJ,cACA,cACA,QAAgB,UACsB;AACtC,UAAM,SAAS,IAAI,gBAAgB;AAAA,MACjC;AAAA,MACA,eAAe;AAAA,MACf,eAAe;AAAA,IACjB,CAAC;AACD,UAAM,MAAM,MAAM,KAAK;AAAA,MACrB,mBAAmB,OAAO,SAAS,CAAC;AAAA,IACtC;AACA,QAAI,IAAI,WAAW,EAAG,QAAO;AAC7B,UAAM,KAAK,IAAI,CAAC;AAChB,QAAI,CAAC,GAAG,WAAW,GAAG,KAAK;AACzB,SAAG,UAAU,KAAK,qBAAqB,GAAG,GAAG;AAAA,IAC/C;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,qBAAqB,OAAuB;AAClD,WAAO,GAAG,KAAK,MAAM,IAAI,KAAK,WAAW,mBAAmB,KAAK;AAAA,EACnE;AAAA,EAEA,MAAM,WAAW,UAAyC;AACxD,UAAM,WAAW,GAAG,aAAa,QAAQ;AACzC,UAAM,WAAW,KAAK,SAAS,QAAQ;AACvC,UAAM,WAAW,SAAS,SAAS,MAAM,IAAI,cAAc;AAC3D,UAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,GAAG,EAAE,MAAM,SAAS,CAAC;AAEpD,UAAM,WAAW,IAAI,SAAS;AAC9B,aAAS,OAAO,QAAQ,MAAM,QAAQ;AAEtC,UAAM,MAAM,GAAG,KAAK,cAAc;AAClC,IAAAA,QAAO,MAAM,kBAAkB,EAAE,KAAK,SAAS,CAAC;AAEhD,UAAM,OAAO,MAAM,MAAM,KAAK;AAAA,MAC5B,QAAQ;AAAA,MACR,SAAS,EAAE,iBAAiB,KAAK,MAAM;AAAA,MACvC,MAAM;AAAA,IACR,CAAC;AAED,QAAI,CAAC,KAAK,IAAI;AACZ,YAAM,OAAO,MAAM,KAAK,KAAK;AAC7B,YAAM,IAAI,oBAAoB,KAAK,QAAQ,yBAAyB,KAAK,MAAM,KAAK,IAAI,IAAI,IAAI;AAAA,IAClG;AAEA,UAAM,SAAU,MAAM,KAAK,KAAK;AAChC,IAAAA,QAAO,KAAK,iBAAiB,EAAE,UAAU,KAAK,OAAO,IAAI,CAAC;AAC1D,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,uBAAuB,OAAe,MAA6B;AACvE,UAAM,aAAa,OAAO;AAC1B,UAAM,KAAK,QAAQ,mBAAmB,KAAK,UAAU;AAAA,MACnD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAAA,IAC3C,CAAC;AACD,IAAAA,QAAO,KAAK,8BAA8B,EAAE,MAAM,CAAC;AAAA,EACrD;AAAA,EAEA,MAAM,kBAAkB,OAA8B;AACpD,UAAM,KAAK,QAAQ,mBAAmB,KAAK,IAAI;AAAA,MAC7C,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,aAAa,QAAQ,CAAC;AAAA,IAC/C,CAAC;AACD,IAAAA,QAAO,KAAK,wBAAwB,EAAE,MAAM,CAAC;AAAA,EAC/C;AAAA,EAEA,MAAM,YAAY,SAAgC;AAChD,UAAM,KAAK,QAAQ,WAAW,OAAO,IAAI,EAAE,QAAQ,SAAS,CAAC;AAC7D,IAAAA,QAAO,KAAK,iBAAiB,EAAE,QAAQ,CAAC;AAAA,EAC1C;AAAA,EAEA,MAAM,WAAW,SAAgC;AAC/C,UAAM,KAAK,QAAQ,WAAW,OAAO,IAAI;AAAA,MACvC,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,aAAa,SAAS,QAAQ,0BAA0B,CAAC;AAAA,IAClF,CAAC;AACD,IAAAA,QAAO,KAAK,gBAAgB,EAAE,QAAQ,CAAC;AAAA,EACzC;AAAA,EAEA,MAAM,eAAe,SAA0C;AAC7D,UAAM,WAA2B,CAAC;AAClC,QAAI,OAAO;AACX,WAAO,MAAM;AACX,YAAM,SAAS,IAAI,gBAAgB,EAAE,UAAU,OAAO,MAAM,OAAO,IAAI,EAAE,CAAC;AAC1E,YAAM,QAAQ,MAAM,KAAK;AAAA,QACvB,WAAW,OAAO,UAAU,OAAO,SAAS,CAAC;AAAA,MAC/C;AACA,eAAS,KAAK,GAAG,KAAK;AACtB,UAAI,MAAM,SAAS,IAAK;AACxB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,gBAAgB,SAAiB,QAA+B;AAEpE,UAAM,KAAK,QAAQ,WAAW,OAAO,UAAU,MAAM,IAAI;AAAA,MACvD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAAA,IAC5D,CAAC;AACD,IAAAA,QAAO,MAAM,wCAAwC,EAAE,SAAS,OAAO,CAAC;AAAA,EAC1E;AAAA,EAEA,MAAM,kBAAkB,SAAkC;AACxD,UAAM,QAAQ,MAAM,KAAK,eAAe,OAAO;AAC/C,UAAM,aAAa,MAAM,OAAO,OAAK,EAAE,KAAK,SAAS,yBAAyB,CAAC;AAC/E,eAAW,QAAQ,YAAY;AAC7B,YAAM,KAAK,gBAAgB,SAAS,KAAK,EAAE;AAAA,IAC7C;AACA,QAAI,WAAW,SAAS,GAAG;AACzB,MAAAA,QAAO,KAAK,0BAA0B,EAAE,SAAS,SAAS,WAAW,OAAO,CAAC;AAAA,IAC/E;AACA,WAAO,WAAW;AAAA,EACpB;AAAA,EAEA,MAAM,sBAAsB,OAAoD;AAC9E,UAAM,KAAK,MAAM,KAAK,QAAoC,mBAAmB,KAAK,EAAE;AACpF,QAAI,CAAC,GAAG,WAAW,GAAG,KAAK;AACzB,SAAG,UAAU,KAAK,qBAAqB,GAAG,GAAG;AAAA,IAC/C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,cAAiBC,QAAc,UAAuB,CAAC,GAAe;AAClF,UAAM,MAAM,GAAG,KAAK,MAAM,GAAGA,MAAI;AACjC,IAAAD,QAAO,MAAM,wBAAwB,EAAE,QAAQ,QAAQ,UAAU,OAAO,IAAI,CAAC;AAE7E,UAAM,OAAO,MAAM,KAAK,eAAe;AAAA,MAAQ,MAC7C,KAAK,YAAY,QAAQ,YAAY;AACnC,cAAM,IAAI,MAAM,MAAM,KAAK;AAAA,UACzB,GAAG;AAAA,UACH,SAAS;AAAA,YACP,iBAAiB,KAAK;AAAA,YACtB,gBAAgB;AAAA,YAChB,GAAG,QAAQ;AAAA,UACb;AAAA,QACF,CAAC;AAED,YAAI,CAAC,EAAE,IAAI;AACT,gBAAM,OAAO,MAAM,EAAE,KAAK;AAC1B,gBAAM,IAAI,iBAAiB,EAAE,QAAQ,sBAAsB,EAAE,MAAM,KAAK,IAAI,IAAI,IAAI;AAAA,QACtF;AAEA,eAAO;AAAA,MACT,GAAG,iBAAiB,QAAQ,UAAU,KAAK,IAAIC,MAAI,EAAE;AAAA,IACvD;AAEA,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA;AAAA,EAGA,MAAM,iBAAwC;AAC5C,WAAO,KAAK,cAA4B,cAAc;AAAA,EACxD;AAAA;AAAA,EAGA,MAAM,iBAAiB,SAAiB,UAAiC;AACvE,UAAM,KAAK,QAAQ,WAAW,OAAO,IAAI;AAAA,MACvC,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,gBAAgB,SAAS,CAAC;AAAA,IACnD,CAAC;AACD,IAAAD,QAAO,KAAK,0BAA0B,EAAE,SAAS,SAAS,CAAC;AAAA,EAC7D;AAAA;AAAA,EAGA,MAAM,mBAAmB,SAAgC;AACvD,UAAM,KAAK,QAAQ,WAAW,OAAO,IAAI;AAAA,MACvC,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,gBAAgB,GAAG,CAAC;AAAA,IAC7C,CAAC;AACD,IAAAA,QAAO,KAAK,0BAA0B,EAAE,QAAQ,CAAC;AAAA,EACnD;AAAA;AAAA,EAGA,MAAM,gBAAgB,SAAiB,QAAgB,MAA6B;AAClF,UAAM,KAAK,QAAQ,WAAW,OAAO,UAAU,MAAM,IAAI;AAAA,MACvD,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,KAAK,CAAC;AAAA,IAC/B,CAAC;AACD,IAAAA,QAAO,MAAM,sBAAsB,EAAE,SAAS,OAAO,CAAC;AAAA,EACxD;AAAA;AAAA,EAGA,MAAM,qBAAqB,SAAiB,MAAqC;AAC/E,UAAM,OAAO,MAAM,KAAK,QAAsB,WAAW,OAAO,UAAU;AAAA,MACxE,QAAQ;AAAA,MACR,MAAM,KAAK,UAAU,EAAE,KAAK,CAAC;AAAA,IAC/B,CAAC;AACD,IAAAA,QAAO,MAAM,8BAA8B,EAAE,SAAS,QAAQ,KAAK,GAAG,CAAC;AACvE,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,aAAa,QAA8B;AACzC,SAAK,SAAS,OAAO,OAAO,QAAQ,OAAO,EAAE;AAC7C,SAAK,QAAQ,OAAO;AACpB,SAAK,cAAc,OAAO;AAC1B,IAAAA,QAAO,KAAK,iCAAiC,EAAE,QAAQ,KAAK,QAAQ,aAAa,KAAK,YAAY,CAAC;AAAA,EACrG;AAAA;AAAA,EAGA,MAAM,uBAAuB,SAAiB,QAA+B;AAC3E,UAAM,QAAQ,MAAM,KAAK,eAAe,OAAO;AAC/C,UAAM,WAAW,MAAM,OAAO,OAAO,OAAK,MAAM,UAAU,CAAC,EAAE,WAAW,SAAS,GAAG,CAAC;AACrF,QAAI,SAAS,WAAW,MAAM,OAAO,OAAQ;AAC7C,UAAM,KAAK,kBAAkB,SAAS,QAAQ;AAAA,EAChD;AAAA,EAEA,MAAM,SAAS,SAAiB,OAA8B;AAC5D,UAAM,QAAQ,MAAM,KAAK,eAAe,OAAO;AAC/C,QAAI,MAAM,OAAO,SAAS,KAAK,GAAG;AAChC,MAAAA,QAAO,KAAK,kCAAkC,EAAE,SAAS,MAAM,CAAC;AAChE;AAAA,IACF;AACA,UAAM,YAAY,CAAC,GAAG,MAAM,QAAQ,KAAK;AACzC,UAAM,KAAK,kBAAkB,SAAS,SAAS;AAAA,EACjD;AACF;;;AGncO,IAAK,aAAL,kBAAKE,gBAAL;AACL,EAAAA,YAAA,aAAU;AACV,EAAAA,YAAA,aAAU;AACV,EAAAA,YAAA,mBAAgB;AAGhB,EAAAA,YAAA,kBAAe;AAEf,EAAAA,YAAA,eAAY;AAEZ,EAAAA,YAAA,kBAAe;AAEf,EAAAA,YAAA,mBAAgB;AAEhB,EAAAA,YAAA,uBAAoB;AAEpB,EAAAA,YAAA,eAAY;AACZ,EAAAA,YAAA,YAAS;AAjBC,SAAAA;AAAA,GAAA;;;ACQZ,IAAMC,UAAS,OAAW,MAAM,cAAc;AAM9C,IAAM,sBAA+E;AAAA,EACnF,WAAiB,EAAE,OAAO,iBAAiB,cAAc,WAAW;AAAA,EACpE,eAAiB,EAAE,OAAO,cAAiB,cAAc,WAAW;AAAA,EACpE,WAAiB,EAAE,OAAO,iBAAiB,cAAc,SAAS;AAAA,EAClE,aAAiB,EAAE,OAAO,cAAiB,cAAc,SAAS;AAAA,EAClE,cAAiB,EAAE,OAAO,iBAAiB,cAAc,YAAY;AAAA,EACrE,gBAAiB,EAAE,OAAO,cAAiB,cAAc,YAAY;AAAA,EACrE,UAAiB,EAAE,OAAO,iBAAiB,cAAc,OAAO;AAAA,EAChE,WAAiB,EAAE,OAAO,cAAiB,cAAc,OAAO;AAAA,EAChE,UAAiB,EAAE,OAAO,iBAAiB,cAAc,QAAQ;AAAA,EACjE,YAAiB,EAAE,OAAO,cAAiB,cAAc,QAAQ;AAAA,EACjE,WAAiB,EAAE,OAAO,iBAAiB,cAAc,SAAS;AAAA;AAAA,EAElE,oBAAoB,EAAE,OAAO,iBAAkB,cAAc,SAAS;AAAA,EACtE,iBAAoB,EAAE,OAAO,kBAAkB,cAAc,SAAS;AACxE;AAEO,IAAM,eAAN,cAA2B,YAAyB;AAAA,EACjD;AAAA,EAER,YAAY,SAAiB,mBAAwD;AACnF,UAAM,SAAS,gBAAgB,UAAU,SAAS;AAClD,SAAK,oBAAoB;AACzB,SAAK,eAAe;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,iBAAuB;AAC7B,QAAI,WAAW;AACf,eAAW,UAAU,KAAK,cAAc,GAAG;AACzC,YAAM,MAAM;AAGZ,YAAM,WAAW,IAAI;AACrB,YAAM,YAAY,oBAAoB,QAAQ;AAC9C,UAAI,WAAW;AACb,YAAI,QAAQ,UAAU;AACtB,YAAI,eAAe,UAAU;AAC7B;AAAA,MACF;AAGA,YAAM,cAAc,IAAI;AACxB,UAAI,aAAa;AACf,cAAM,kBAAkB,oBAAoB,WAAW;AACvD,YAAI,iBAAiB;AACnB,cAAI,gBAAgB,gBAAgB;AAEpC,cAAI,CAAC,IAAI,cAAc;AACrB,gBAAI,eAAe,gBAAgB;AAAA,UACrC;AAAA,QACF;AAAA,MACF;AAGA,UAAI,CAAC,IAAI,cAAc,IAAI,UAAU;AACnC,YAAI,aAAa;AAAA,UACf,UAAU,MAAM,IAAI,QAAQ;AAAA,UAC5B,WAAW;AAAA,YACT,QAAQ;AAAA,YACR,YAAY,OAAO,IAAI,WAAW,IAAI,QAAQ;AAAA,YAC9C,WAAW,OAAO,IAAI,QAAQ;AAAA,UAChC;AAAA,UACA,OAAQ,IAAI,cAAyB;AAAA,UACrC,aAAa;AAAA,UACb,WAAY,IAAI,cAAwB,oBAAI,KAAK,GAAE,YAAY;AAAA,QACjE;AAAA,MACF;AAGA,UAAI,IAAI,YAAY,UAAa,IAAI,aAAa,UAAa,IAAI,eAAe,QAAW;AAC3F,eAAO,IAAI;AACX,eAAO,IAAI;AACX,eAAO,IAAI;AACX;AAAA,MACF;AAAA,IACF;AACA,QAAI,WAAW,GAAG;AAChB,WAAK,KAAK;AACV,MAAAA,QAAO,KAAK,4BAA4B,EAAE,SAAS,CAAC;AAAA,IACtD;AAAA,EACF;AAAA,EAEQ,aAAa,QAA6C;AAChE,QAAI,OAAO,cAAc;AACvB,YAAM,KAAK,KAAK,kBAAkB,IAAI,OAAO,YAAY;AACzD,UAAI,GAAI,QAAO;AAAA,IACjB;AAEA,WAAO,KAAK,kBAAkB,IAAI,WAAW,KAAK,KAAK,kBAAkB,OAAO,EAAE,KAAK,EAAE;AAAA,EAC3F;AAAA,EAEQ,IAAI,UAA0B;AACpC,WAAO,OAAO,QAAQ;AAAA,EACxB;AAAA,EAEA,IAAI,UAA2C;AAC7C,WAAO,KAAK,SAAS,KAAK,IAAI,QAAQ,CAAC;AAAA,EACzC;AAAA,EAEA,OAAO,QAAgF;AACrF,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,UAAM,OAAoB;AAAA,MACxB,GAAG;AAAA,MACH,UAAU;AAAA,MACV,WAAW;AAAA,MACX,WAAW;AAAA,IACb;AACA,SAAK,UAAU,KAAK,IAAI,OAAO,IAAI,CAAC,GAAG,IAAI;AAC3C,SAAK,KAAK;AACV,IAAAA,QAAO,KAAK,iBAAiB,EAAE,UAAU,OAAO,IAAI,GAAG,OAAO,OAAO,MAAM,CAAC;AAC5E,aAAS,UAAU,iBAAiB,IAAI;AACxC,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,UAAkB,OAAmB,OAAoC;AACnF,UAAM,SAAS,KAAK,WAAW,KAAK,IAAI,QAAQ,CAAC;AACjD,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI,mBAAmB,QAAQ;AAAA,IACvC;AACA,WAAO,QAAQ;AACf,WAAO,aAAY,oBAAI,KAAK,GAAE,YAAY;AAC1C,QAAI,uCAAgC;AAClC,aAAO,YAAY;AACnB,aAAO,gBAAgB;AAAA,IACzB;AACA,QAAI,OAAO;AACT,aAAO,OAAO,QAAQ,KAAK;AAAA,IAC7B;AACA,SAAK,KAAK;AACV,IAAAA,QAAO,KAAK,uBAAuB,EAAE,UAAU,MAAM,CAAC;AACtD,aAAS,UAAU,sBAAsB,EAAE,UAAU,OAAO,OAAO,CAAC;AAAA,EACtE;AAAA,EAEA,WAAW,UAAkB,OAAe,eAAiC;AAC3E,UAAM,SAAS,KAAK,WAAW,KAAK,IAAI,QAAQ,CAAC;AACjD,QAAI,CAAC,OAAQ;AACb,WAAO;AACP,WAAO,YAAY;AACnB,WAAO,gBAAgB;AACvB,WAAO,YAAY;AACnB,WAAO,aAAY,oBAAI,KAAK,GAAE,YAAY;AAC1C,SAAK,KAAK;AACV,IAAAA,QAAO,KAAK,0BAA0B,EAAE,UAAU,OAAO,eAAe,UAAU,OAAO,SAAS,CAAC;AACnG,aAAS,UAAU,gBAAgB,EAAE,UAAU,OAAO,eAAe,OAAO,CAAC;AAAA,EAC/E;AAAA,EAEA,aAAa,UAA2B;AACtC,UAAM,SAAS,KAAK,IAAI,QAAQ;AAChC,QAAI,CAAC,OAAQ,QAAO;AACpB,WAAO,CAAC,KAAK,aAAa,MAAM,EAAE,WAAW,OAAO,KAAK;AAAA,EAC3D;AAAA,EAEA,YAAY,UAA2B;AACrC,UAAM,SAAS,KAAK,IAAI,QAAQ;AAChC,WAAO,QAAQ;AAAA,EACjB;AAAA,EAEA,SAAS,UAAkB,YAA6B;AACtD,UAAM,SAAS,KAAK,IAAI,QAAQ;AAChC,QAAI,CAAC,UAAU,OAAO,gCAA6B,QAAO;AAC1D,WAAO,OAAO,WAAW;AAAA,EAC3B;AAAA,EAEA,cAAc,UAA0C;AACtD,UAAM,SAAS,KAAK,IAAI,QAAQ;AAChC,WAAO,QAAQ;AAAA,EACjB;AAAA,EAEA,UAAU,UAAkB,cAAsB,IAAI,KAAK,KAAe;AACxE,UAAM,SAAS,KAAK,IAAI,QAAQ;AAChC,QAAI,CAAC,OAAQ,QAAO;AACpB,QAAI,KAAK,aAAa,MAAM,EAAE,UAAU,OAAO,KAAK,EAAG,QAAO;AAC9D,QAAI,CAAC,KAAK,aAAa,QAAQ,EAAG,QAAO;AACzC,UAAM,UAAU,KAAK,IAAI,IAAI,IAAI,KAAK,OAAO,SAAS,EAAE,QAAQ;AAChE,WAAO,UAAU;AAAA,EACnB;AAAA,EAEA,kBAAkB,YAAoB,oBAA4C;AAChF,WAAO,KAAK,cAAc,EAAE,OAAO,CAAC,WAAW;AAC7C,YAAM,KAAK,KAAK,aAAa,MAAM;AACnC,UAAI,GAAG,WAAW,OAAO,OAAO,OAAO,UAAU,UAAU,EAAG,QAAO;AACrE,UAAI,KAAK,UAAU,OAAO,MAAM,GAAG,kBAAkB,EAAG,QAAO;AAC/D,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEA,eAA8B;AAC5B,WAAO,KAAK,cAAc,EAAE;AAAA,MAC1B,CAAC,MAAM,CAAC,KAAK,aAAa,CAAC,EAAE,WAAW,EAAE,KAAK;AAAA,IACjD;AAAA,EACF;AAAA,EAEA,SAAwB;AACtB,WAAO,KAAK,cAAc;AAAA,EAC5B;AAAA,EAEA,aAAa,UAA2B;AACtC,UAAM,SAAS,KAAK,WAAW,KAAK,IAAI,QAAQ,CAAC;AACjD,QAAI,CAAC,UAAU,OAAO,kCAA8B,QAAO;AAC3D,WAAO;AACP,WAAO,aAAY,oBAAI,KAAK,GAAE,YAAY;AAC1C,SAAK,KAAK;AACV,IAAAA,QAAO,KAAK,yBAAyB,EAAE,SAAS,CAAC;AACjD,aAAS,UAAU,sBAAsB,EAAE,UAAU,gCAA2B,OAAO,CAAC;AACxF,WAAO;AAAA,EACT;AAAA,EAEA,UAAU,UAA2B;AACnC,UAAM,SAAS,KAAK,WAAW,KAAK,IAAI,QAAQ,CAAC;AACjD,QAAI,CAAC,OAAQ,QAAO;AACpB,WAAO;AACP,WAAO,WAAW;AAClB,WAAO,gBAAgB;AACvB,WAAO,YAAY;AACnB,WAAO,aAAY,oBAAI,KAAK,GAAE,YAAY;AAC1C,SAAK,KAAK;AACV,IAAAA,QAAO,KAAK,qBAAqB,EAAE,SAAS,CAAC;AAC7C,aAAS,UAAU,mBAAmB,EAAE,UAAU,OAAO,CAAC;AAC1D,WAAO;AAAA,EACT;AAAA,EAEA,aAAa,UAAkB,OAAe,KAA2B;AACvE,UAAM,SAAS,KAAK,WAAW,KAAK,IAAI,QAAQ,CAAC;AACjD,QAAI,CAAC,OAAQ,QAAO;AAGpB,UAAM,KAAK,KAAK,kBAAkB,IAAI,IAAI,IAAI,KAAK,KAAK,aAAa,MAAM;AAC3E,UAAM,cAAc,GAAG,iBAAiB,KAAK;AAC7C,QAAI,CAAC,YAAa,QAAO;AACzB,WAAO,QAAQ;AAEf,QAAI,sDAA2C,gDACxC,sDAA2C,sDAA0C;AAK1F,YAAM,SAAS,IAAI;AACnB,YAAM,MAAM,OAAO,UAAU,OAAK,EAAE,SAAS,KAAK;AAClD,UAAI,MAAM,GAAG;AACX,eAAO,eAAe,OAAO,MAAM,CAAC,EAAE;AAAA,MACxC;AAAA,IACF;AACA,WAAO,gBAAgB;AACvB,WAAO,YAAY;AACnB,WAAO,aAAY,oBAAI,KAAK,GAAE,YAAY;AAC1C,SAAK,KAAK;AACV,IAAAA,QAAO,KAAK,wBAAwB,EAAE,UAAU,OAAO,OAAO,YAAY,CAAC;AAC3E,aAAS,UAAU,wBAAwB,EAAE,UAAU,OAAO,OAAO,CAAC;AACtE,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,UAA2B;AACvC,UAAM,SAAS,KAAK,WAAW,KAAK,IAAI,QAAQ,CAAC;AACjD,QAAI,CAAC,UAAU,OAAO,gCAA6B,QAAO;AAE1D,UAAM,eAAe,OAAO;AAC5B,WAAO,QAAQ;AACf,WAAO,YAAY;AACnB,WAAO,aAAY,oBAAI,KAAK,GAAE,YAAY;AAC1C,SAAK,KAAK;AACV,IAAAA,QAAO,KAAK,yBAAyB,EAAE,UAAU,aAAa,CAAC;AAC/D,aAAS,UAAU,uBAAuB,EAAE,UAAU,cAAc,OAAO,CAAC;AAC5E,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,UAA2B;AAChC,UAAM,MAAM,KAAK,IAAI,QAAQ;AAC7B,UAAM,SAAS,KAAK,WAAW,GAAG;AAClC,QAAI,CAAC,OAAQ,QAAO;AACpB,WAAO,KAAK,WAAW,GAAG;AAC1B,SAAK,KAAK;AACV,IAAAA,QAAO,KAAK,8BAA8B,EAAE,SAAS,CAAC;AACtD,aAAS,UAAU,iBAAiB,EAAE,UAAU,OAAO,CAAC;AACxD,WAAO;AAAA,EACT;AAAA,EAEA,2BAAmC;AACjC,QAAI,QAAQ;AACZ,eAAW,UAAU,KAAK,cAAc,GAAG;AACzC,YAAM,KAAK,KAAK,aAAa,MAAM;AACnC,UAAI,GAAG,aAAa,OAAO,KAAK,GAAG;AACjC,cAAM,MAAM,OAAO,MAAM;AACzB,QAAAA,QAAO,KAAK,gCAAgC;AAAA,UAC1C,UAAU;AAAA,UACV,OAAO,OAAO;AAAA,QAChB,CAAC;AACD,eAAO,gBAAgB,OAAO;AAC9B,eAAO;AACP,eAAO,YAAY;AACnB,eAAO,YAAY;AACnB,eAAO,aAAY,oBAAI,KAAK,GAAE,YAAY;AAC1C;AACA,iBAAS,UAAU,gBAAgB;AAAA,UACjC,UAAU;AAAA,UACV,OAAO;AAAA,UACP,eAAe,OAAO;AAAA,UACtB;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AACA,QAAI,QAAQ,GAAG;AACb,WAAK,KAAK;AACV,MAAAA,QAAO,KAAK,gCAAgC,EAAE,MAAM,CAAC;AAAA,IACvD;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,oBAAsC;AACpC,WAAO,KAAK,cAAc,EAAE,IAAI,CAAC,WAAW;AAC1C,YAAM,KAAK,KAAK,aAAa,MAAM;AACnC,aAAO,sBAAsB,QAAQ,EAAE;AAAA,IACzC,CAAC;AAAA,EACH;AACF;;;ACnVA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAKjB,IAAMC,UAAS,OAAW,MAAM,iBAAiB;AAEjD,IAAM,WAAW;AAQV,IAAM,kBAAN,MAAM,iBAAgB;AAAA,EACnB;AAAA,EACA;AAAA,EAER,YAAY,SAAiB,UAAkB;AAC7C,SAAK,UAAU;AACf,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,IAAI,UAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAY,UAAkB;AAC5B,WAAOC,MAAK,KAAK,KAAK,SAAS,UAAU,SAAS,KAAK,QAAQ,EAAE;AAAA,EACnE;AAAA,EAEA,YAAkB;AAChB,QAAI,CAACC,IAAG,WAAW,KAAK,OAAO,GAAG;AAChC,MAAAA,IAAG,UAAU,KAAK,SAAS,EAAE,WAAW,KAAK,CAAC;AAAA,IAChD;AAAA,EACF;AAAA,EAEA,eAAe,MAAyF;AACtG,SAAK,UAAU;AACf,UAAM,WAAWD,MAAK,KAAK,KAAK,SAAS,iBAAiB;AAC1D,IAAAC,IAAG,cAAc,UAAU,KAAK,UAAU,MAAM,MAAM,CAAC,GAAG,OAAO;AACjE,IAAAF,QAAO,KAAK,oBAAoB;AAAA,EAClC;AAAA,EAEA,cAAc,MAA0B;AACtC,SAAK,UAAU;AACf,UAAM,WAAWC,MAAK,KAAK,KAAK,SAAS,eAAe;AACxD,IAAAC,IAAG,cAAc,UAAU,KAAK,UAAU,MAAM,MAAM,CAAC,GAAG,OAAO;AACjE,IAAAF,QAAO,MAAM,oBAAoB,EAAE,cAAc,KAAK,aAAa,CAAC;AAAA,EACtE;AAAA,EAEA,eAAoC;AAClC,UAAM,WAAWC,MAAK,KAAK,KAAK,SAAS,eAAe;AACxD,QAAI,CAACC,IAAG,WAAW,QAAQ,EAAG,QAAO;AACrC,QAAI;AACF,aAAO,KAAK,MAAMA,IAAG,aAAa,UAAU,OAAO,CAAC;AAAA,IACtD,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,cAAc,SAAuB;AACnC,SAAK,UAAU;AACf,IAAAA,IAAG,cAAcD,MAAK,KAAK,KAAK,SAAS,gBAAgB,GAAG,SAAS,OAAO;AAC5E,IAAAD,QAAO,KAAK,2BAA2B;AAAA,EACzC;AAAA,EAEA,YAAY,SAAuB;AACjC,SAAK,UAAU;AACf,IAAAE,IAAG,cAAcD,MAAK,KAAK,KAAK,SAAS,cAAc,GAAG,SAAS,OAAO;AAC1E,IAAAD,QAAO,KAAK,yBAAyB;AAAA,EACvC;AAAA,EAEA,cAAc,SAAuB;AACnC,SAAK,UAAU;AACf,IAAAE,IAAG,cAAcD,MAAK,KAAK,KAAK,SAAS,gBAAgB,GAAG,SAAS,OAAO;AAC5E,IAAAD,QAAO,KAAK,kBAAkB;AAAA,EAChC;AAAA,EAEA,kBAAkB,SAAiB,WAAW,uBAA6B;AACzE,SAAK,UAAU;AACf,IAAAE,IAAG,cAAcD,MAAK,KAAK,KAAK,SAAS,QAAQ,GAAG,SAAS,OAAO;AACpE,IAAAD,QAAO,KAAK,yBAAyB,EAAE,SAAS,CAAC;AAAA,EACnD;AAAA,EAEA,kBAA4B;AAC1B,QAAI,CAACE,IAAG,WAAW,KAAK,OAAO,EAAG,QAAO,CAAC;AAC1C,WAAOA,IAAG,YAAY,KAAK,OAAO,EAAE,IAAI,CAAC,MAAMD,MAAK,KAAK,UAAU,SAAS,KAAK,QAAQ,IAAI,CAAC,CAAC;AAAA,EACjG;AAAA,EAEA,sBAAsB,WAAmB,OAAe,YAAoB,KAAiC;AAC3G,UAAM,UAAyB,EAAE,QAAQ,UAAU;AACnD,QAAI,KAAK;AACP,YAAM,SAAwC,CAAC;AAC/C,iBAAW,QAAQ,IAAI,QAAQ;AAC7B,eAAO,KAAK,IAAI,IAAI,EAAE,GAAG,QAAQ;AAAA,MACnC;AACA,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,QACA,cAAc,IAAI;AAAA,QAClB,cAAc,IAAI,OAAO,CAAC,EAAE;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,QAAQ;AAAA,QACN,UAAU,EAAE,GAAG,QAAQ;AAAA,QACvB,QAAQ,EAAE,GAAG,QAAQ;AAAA,QACrB,WAAW,EAAE,GAAG,QAAQ;AAAA,QACxB,QAAQ,EAAE,GAAG,QAAQ;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,UAAU,SAAuB;AAC/B,SAAK,UAAU;AACf,IAAAC,IAAG,cAAcD,MAAK,KAAK,KAAK,SAAS,YAAY,GAAG,SAAS,OAAO;AACxE,IAAAD,QAAO,KAAK,uBAAuB;AAAA,EACrC;AAAA,EAEA,oBAAoB,SAAuB;AACzC,SAAK,UAAU;AACf,UAAM,UAAU,KAAK,kBAAkB;AACvC,UAAM,QAAqB;AAAA,MACzB,OAAO,QAAQ,SAAS;AAAA,MACxB,UAAU;AAAA,MACV,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AACA,YAAQ,KAAK,KAAK;AAClB,IAAAE,IAAG;AAAA,MACDD,MAAK,KAAK,KAAK,SAAS,qBAAqB;AAAA,MAC7C,KAAK,UAAU,SAAS,MAAM,CAAC;AAAA,MAC/B;AAAA,IACF;AACA,IAAAC,IAAG;AAAA,MACDD,MAAK,KAAK,KAAK,SAAS,oBAAoB;AAAA,MAC5C,iBAAgB,4BAA4B,OAAO;AAAA,MACnD;AAAA,IACF;AACA,IAAAD,QAAO,KAAK,4BAA4B,EAAE,OAAO,MAAM,MAAM,CAAC;AAAA,EAChE;AAAA,EAEA,qBAAoC;AAClC,UAAM,WAAWC,MAAK,KAAK,KAAK,SAAS,oBAAoB;AAC7D,QAAI,CAACC,IAAG,WAAW,QAAQ,EAAG,QAAO;AACrC,QAAI;AACF,aAAOA,IAAG,aAAa,UAAU,OAAO;AAAA,IAC1C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,oBAAmC;AACjC,UAAM,WAAWD,MAAK,KAAK,KAAK,SAAS,qBAAqB;AAC9D,QAAI,CAACC,IAAG,WAAW,QAAQ,EAAG,QAAO,CAAC;AACtC,QAAI;AACF,YAAM,OAAO,KAAK,MAAMA,IAAG,aAAa,UAAU,OAAO,CAAC;AAC1D,aAAO,MAAM,QAAQ,IAAI,IAAI,OAAO,CAAC;AAAA,IACvC,QAAQ;AACN,aAAO,CAAC;AAAA,IACV;AAAA,EACF;AAAA,EAEA,OAAO,4BAA4B,SAAgC;AACjE,QAAI,QAAQ,WAAW,EAAG,QAAO;AACjC,UAAM,QAAQ,CAAC,0CAAY,EAAE;AAC7B,eAAW,KAAK,SAAS;AACvB,YAAM,KAAK,aAAQ,EAAE,KAAK,iCAAQ;AAClC,YAAM,KAAK,mBAAS,EAAE,SAAS,EAAE;AACjC,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,EAAE,QAAQ;AACrB,YAAM,KAAK,EAAE;AAAA,IACf;AACA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAAA,EAEA,oBACE,WACA,QACA,OACM;AACN,UAAM,WAAW,KAAK,aAAa;AACnC,QAAI,CAAC,SAAU;AAEf,UAAM,OAAM,oBAAI,KAAK,GAAE,YAAY;AACnC,QAAI,CAAC,SAAS,OAAO,SAAS,GAAG;AAC/B,eAAS,OAAO,SAAS,IAAI,EAAE,QAAQ,UAAU;AAAA,IACnD;AACA,UAAM,QAAQ,SAAS,OAAO,SAAS;AAEvC,UAAM,SAAS;AACf,QAAI,WAAW,eAAe;AAC5B,YAAM,YAAY;AAClB,eAAS,eAAe;AAAA,IAC1B,WAAW,WAAW,aAAa;AACjC,YAAM,cAAc;AAAA,IACtB,WAAW,WAAW,UAAU;AAC9B,YAAM,QAAQ;AAAA,IAChB;AAEA,SAAK,cAAc,QAAQ;AAAA,EAC7B;AACF;;;AClNA,OAAOC,SAAQ;AACf,OAAOC,WAAU;;;ACDjB,SAAS,SAAS,gBAAgB;AAClC,OAAOC,WAAU;AAUjB,SAAS,iBAAiB,KAA6E;AACrG,QAAM,UAAU;AAChB,QAAM,QAAQ,IAAI,MAAM,OAAO;AAC/B,MAAI,CAAC,OAAO;AACV,WAAO,EAAE,aAAa,IAAI,aAAa,OAAO,SAAS,IAAI,KAAK,EAAE;AAAA,EACpE;AAEA,QAAM,YAAY,MAAM,CAAC;AACzB,QAAM,UAAU,IAAI,MAAM,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK;AAEhD,MAAI,cAAc;AAClB,QAAM,YAAY,UAAU,MAAM,qBAAqB;AACvD,MAAI,WAAW;AACb,kBAAc,UAAU,CAAC,EAAE,KAAK;AAAA,EAClC;AAEA,MAAI,cAAc;AAClB,QAAM,aAAa,UAAU,MAAM,8BAA8B;AACjE,MAAI,YAAY;AACd,kBAAc,WAAW,CAAC,EAAE,YAAY,MAAM;AAAA,EAChD;AAEA,SAAO,EAAE,aAAa,aAAa,QAAQ;AAC7C;AAEO,IAAM,eAAN,MAAmB;AAAA,EAChB,QAAmB,CAAC;AAAA,EACpB;AAAA,EAER,YAAY,cAAoC;AAC9C,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,MAAa,UAAU,UAAiC;AACtD,SAAK,QAAQ,CAAC;AACd,QAAI;AACJ,QAAI;AACF,cAAQ,MAAM,QAAQ,QAAQ;AAAA,IAChC,QAAQ;AACN;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,OAAO,OAAK,EAAE,SAAS,MAAM,CAAC;AAErD,UAAM,eAAe,SAAS,IAAI,OAAO,aAAa;AACpD,UAAI;AACF,cAAM,MAAM,MAAM,SAASA,MAAK,KAAK,UAAU,QAAQ,GAAG,OAAO;AACjE,cAAM,EAAE,aAAa,aAAa,QAAQ,IAAI,iBAAiB,GAAG;AAClE,YAAI,SAAS;AACX,eAAK,MAAM,KAAK,EAAE,UAAU,aAAa,aAAa,QAAQ,CAAC;AAAA,QACjE;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF,CAAC;AAED,UAAM,QAAQ,IAAI,YAAY;AAAA,EAChC;AAAA,EAEO,WAAsB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA,EAEO,WAAW,MAAyB;AACzC,UAAM,YAAY,KAAK,YAAY;AACnC,UAAM,UAAU,oBAAI,IAAqB;AAGzC,eAAW,QAAQ,KAAK,OAAO;AAC7B,UAAI,KAAK,aAAa;AACpB,gBAAQ,IAAI,KAAK,UAAU,IAAI;AAAA,MACjC;AAAA,IACF;AAEA,QAAI,KAAK,YAAY,KAAK,SAAS,SAAS,GAAG;AAE7C,iBAAW,WAAW,KAAK,UAAU;AACnC,YAAI,QAAQ,IAAI,QAAQ,QAAQ,EAAG;AACnC,cAAM,cAAc,QAAQ,SAAS,KAAK,QAAM,UAAU,SAAS,GAAG,YAAY,CAAC,CAAC;AACpF,YAAI,CAAC,YAAa;AAElB,cAAM,OAAO,KAAK,MAAM,KAAK,OAAK,EAAE,aAAa,QAAQ,QAAQ;AACjE,YAAI,MAAM;AACR,kBAAQ,IAAI,KAAK,UAAU,IAAI;AAAA,QACjC;AAAA,MACF;AAAA,IACF,OAAO;AAEL,iBAAW,QAAQ,KAAK,OAAO;AAC7B,YAAI,QAAQ,IAAI,KAAK,QAAQ,EAAG;AAChC,YAAI,CAAC,KAAK,YAAa;AAEvB,cAAM,YAAY,KAAK,YACpB,MAAM,cAAc,EACpB,OAAO,OAAK,EAAE,UAAU,CAAC;AAC5B,cAAM,YAAY,UAAU,KAAK,UAAQ,UAAU,SAAS,KAAK,YAAY,CAAC,CAAC;AAC/E,YAAI,WAAW;AACb,kBAAQ,IAAI,KAAK,UAAU,IAAI;AAAA,QACjC;AAAA,MACF;AAAA,IACF;AAEA,WAAO,MAAM,KAAK,QAAQ,OAAO,CAAC;AAAA,EACpC;AAAA,EAEO,gBAAgB,OAA0B;AAC/C,QAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,WAAO,MAAM,IAAI,UAAQ;AACvB,YAAM,SAAS,KAAK,cAChB,OAAO,KAAK,WAAW,KAAK,KAAK,QAAQ,MACzC,OAAO,KAAK,QAAQ;AACxB,aAAO,GAAG,MAAM;AAAA;AAAA,EAAO,KAAK,OAAO;AAAA,IACrC,CAAC,EAAE,KAAK,aAAa;AAAA,EACvB;AACF;;;AC1HA,IAAI;AAEG,SAAS,mBAAmB,KAAsB;AACvD,SAAO,oBAAoB,IAAI,cAAc;AAC/C;AAEO,SAAS,oBAAoB,OAAkC;AACpE,qBAAmB;AACrB;AAEO,SAAS,0BACd,UACA,SACA,KACS;AACT,QAAM,SAAS,QAAQ,IAAI,QAAQ;AACnC,MAAI,QAAQ,yBAAyB,OAAW,QAAO,OAAO;AAC9D,SAAO,mBAAmB,GAAG;AAC/B;AAEA,IAAM,qBAAqB;AAEpB,SAAS,kBAAkB,SAAyB;AACzD,MAAI,QAAQ,UAAU,mBAAoB,QAAO;AACjD,QAAM,MAAM,QAAQ,MAAM,GAAG,kBAAkB;AAC/C,QAAM,cAAc,IAAI,YAAY,MAAM;AAC1C,QAAM,WAAW,cAAc,qBAAqB,MAAM,cAAc,IAAI,YAAY,IAAI;AAC5F,QAAM,UAAU,WAAW,qBAAqB,MAAM,IAAI,MAAM,GAAG,QAAQ,IAAI;AAC/E,SAAO,UAAU;AACnB;AAOO,SAAS,qBACd,WACA,YACA,QACA,cACA,SACQ;AACR,QAAM,QAAgC;AAAA,IACpC,UAAU;AAAA,IAAM,QAAQ;AAAA,IAAM,WAAW;AAAA,IAAM,QAAQ;AAAA,IACvD,MAAM;AAAA,IAAM,QAAQ;AAAA,IAAM,OAAO;AAAA,EACnC;AACA,QAAM,OAAO,MAAM,SAAS,KAAK;AACjC,SAAO;AAAA,IACL,EAAE,2BAA2B,EAAE,MAAM,OAAO,WAAW,CAAC;AAAA,IACxD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,EAAE,oBAAoB,EAAE,OAAO,YAAY,KAAK,OAAO,CAAC;AAAA,IACxD,EAAE,0BAA0B,EAAE,KAAK,aAAa,CAAC;AAAA,EACnD,EAAE,KAAK,IAAI;AACb;;;AFRO,IAAe,YAAf,MAAe,WAAU;AAAA,EAC9B,OAAwB,qBAAqB;AAAA,EAEnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACF;AAAA,EACE;AAAA,EAIV,IAAI,aAAyB;AAC3B,UAAM,SAAS,KAAK,UAAU,eAAe,KAAK,SAAS;AAC3D,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,UAAU,KAAK,SAAS,kCAAkC;AACvF,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,IAAI,YAAwB;AAC1B,UAAM,SAAS,KAAK,UAAU,eAAe,KAAK,SAAS;AAC3D,QAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,UAAU,KAAK,SAAS,kCAAkC;AACvF,WAAO,OAAO;AAAA,EAChB;AAAA,EAEA,YACE,UACA,KACA,MACA,QACA,WACA,OACA;AACA,SAAK,WAAW;AAChB,SAAK,MAAM;AACX,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,YAAY;AACjB,SAAK,QAAQ;AACb,SAAK,SAAS,OAAW,MAAM,KAAK,YAAY,IAAI;AAAA,EACtD;AAAA,EAIU,aAA2C;AACnD,WAAO;AAAA,EACT;AAAA,EAEU,eAAe,MAAiE;AACxF,WAAO,CAAC;AAAA,EACV;AAAA,EAEA,MAAM,QAAQ,KAAuC;AACnD,UAAM,YAAY,OAAO,IAAI,OAAO,UAAU,SAAS;AACvD,SAAK,OAAO,KAAK,SAAS,KAAK,SAAS,aAAa,EAAE,UAAU,UAAU,CAAC;AAG5E,UAAM,KAAK,iBAAiB;AAC5B,SAAK,KAAK,oBAAoB,KAAK,WAAW,aAAa;AAG3D,UAAM,KAAK;AAAA,MACT,qBAAqB,KAAK,WAAW,aAAa;AAAA,IACpD;AAEA,UAAM,aAAa,EAAE,SAAS,KAAK,SAAS,EAAE,KAAK,KAAK;AACxD,aAAS,UAAU,gBAAgB;AAAA,MACjC,UAAU;AAAA,MACV,OAAO,KAAK;AAAA,MACZ,OAAO;AAAA,QACL,MAAM;AAAA,QACN,SAAS,EAAE,wBAAwB,EAAE,OAAO,WAAW,CAAC;AAAA,QACxD,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC;AAAA,IACF,CAAC;AAGD,UAAM,aAAa,KAAK,YAAY,GAAG;AACvC,UAAM,mBAAmB,MAAM,KAAK,aAAa,GAAG;AACpD,UAAM,SAAS,mBACX,GAAG,UAAU;AAAA;AAAA,EAAO,EAAE,0BAA0B,EAAE,OAAO,iBAAiB,CAAC,CAAC,KAC5E;AAEJ,UAAM,SAAS,MAAM,KAAK,SAAS,IAAI;AAAA,MACrC;AAAA,MACA,SAAS,KAAK,KAAK;AAAA,MACnB,WAAW,KAAK,OAAO,GAAG;AAAA,MAC1B,eAAe,KAAK,OAAO,GAAG;AAAA,MAC9B,MAAM,KAAK,WAAW;AAAA,MACtB,eAAe,CAAC,UAAU;AACxB,iBAAS,UAAU,gBAAgB;AAAA,UACjC,UAAU;AAAA,UACV,OAAO,KAAK;AAAA,UACZ;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAED,QAAI,CAAC,OAAO,SAAS;AAEnB,YAAM,cAAc,OAAO,gBAAgB,OAAO,QAAQ,MAAM,GAAG,GAAG;AACtE,YAAM,eAAe,OAAO,gBAAgB,OAAO,QAAQ,MAAM,GAAG,GAAG;AAEvE,WAAK,KAAK,oBAAoB,KAAK,WAAW,UAAU,UAAU;AAClE,YAAM,KAAK,kBAAkB,UAAU;AAEvC,YAAM,KAAK;AAAA,QACT,qBAAqB,KAAK,WAAW,UAAU,EAAE,mBAAmB,EAAE,SAAS,YAAY,CAAC,CAAC;AAAA,MAC/F;AAEA,YAAM,IAAI,iBAAiB,KAAK,WAAW,SAAS,KAAK,SAAS,YAAY,WAAW,IAAI;AAAA,QAC3F,QAAQ,OAAO;AAAA,QACf,UAAU,OAAO;AAAA,MACnB,CAAC;AAAA,IACH;AAEA,UAAM,KAAK,oBAAoB,KAAK,SAAS;AAE7C,UAAM,KAAK,gBAAgB;AAC3B,SAAK,KAAK,oBAAoB,KAAK,WAAW,WAAW;AAEzD,UAAM,KAAK,gBAAgB,KAAK,SAAS;AAEzC,UAAM,KAAK,kBAAkB,KAAK,SAAS;AAE3C,SAAK,OAAO,KAAK,SAAS,KAAK,SAAS,cAAc,EAAE,UAAU,UAAU,CAAC;AAC7E,WAAO;AAAA,EACT;AAAA;AAAA,EAIA,MAAc,mBAAkC;AAC9C,UAAM,KAAK,MAAM,aAAa,KAAK,SAAS;AAAA,EAC9C;AAAA,EAEA,MAAc,kBAAiC;AAC7C,UAAM,KAAK,MAAM,YAAY,KAAK,SAAS;AAAA,EAC7C;AAAA,EAEA,MAAc,kBAAkB,OAA8B;AAC5D,UAAM,KAAK,MAAM,cAAc,KAAK,WAAW,KAAK;AAAA,EACtD;AAAA,EAEA,MAAc,cAAc,SAAgC;AAC1D,QAAI;AACF,YAAM,KAAK,MAAM,UAAU,OAAO;AAAA,IACpC,SAAS,KAAK;AACZ,WAAK,OAAO,KAAK,yBAAyB,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IAC7E;AAAA,EACF;AAAA,EAEA,MAAgB,aAAa,KAA2C;AACtE,QAAI;AACF,YAAM,WAAWC,MAAK,KAAK,KAAK,KAAK,SAAS,WAAW,OAAO;AAChE,YAAM,YAAY,oBAAoB;AACtC,YAAM,WAAW,IAAI,aAAa,WAAW,YAAY;AACzD,YAAM,SAAS,UAAU,QAAQ;AACjC,YAAM,UAAU,GAAG,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,WAAW,IAAI,IAAI,OAAO,aAAa,KAAK,UAAU,IAAI,OAAO,UAAU,IAAI,EAAE;AACnI,YAAM,UAAU,SAAS,WAAW,OAAO;AAC3C,UAAI,QAAQ,SAAS,GAAG;AACtB,aAAK,OAAO,KAAK,WAAW,QAAQ,MAAM,cAAc;AAAA,UACtD,OAAO,QAAQ,IAAI,OAAK,EAAE,QAAQ;AAAA,QACpC,CAAC;AACD,eAAO,SAAS,gBAAgB,OAAO;AAAA,MACzC;AAAA,IACF,SAAS,KAAK;AACZ,WAAK,OAAO,KAAK,+BAA+B,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACnF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,kBAAkB,KAAmB,WAAkC;AACnF,QAAI;AACF,YAAM,UAAU,KAAK,MAAM,kBAAkB;AAC7C,YAAM,cAAc,KAAK,eAAe,GAAG;AAE3C,UAAI,CAAC,WAAW,YAAY,WAAW,GAAG;AACxC,cAAM,KAAK;AAAA,UACT,qBAAqB,KAAK,WAAW,WAAW;AAAA,QAClD;AACA;AAAA,MACF;AAEA,YAAM,UAAU,KAAK,OAAO,cAAc,WAAW,QAAQ,OAAO,EAAE;AACtE,YAAM,aAAa,EAAE,SAAS,KAAK,SAAS,EAAE,KAAK,KAAK;AACxD,YAAM,eAAe,GAAG,OAAO,WAAW,SAAS;AAEnD,iBAAW,QAAQ,aAAa;AAC9B,cAAM,UAAU,KAAK,eAAe,WAAW,KAAK,QAAQ;AAC5D,YAAI,CAAC,QAAS;AAEd,cAAM,UAAU,kBAAkB,OAAO;AACzC,cAAM,SAAS,GAAG,OAAO,QAAQ,SAAS,IAAI,KAAK,QAAQ;AAC3D,cAAM,UAAU;AAAA,UACd,KAAK;AAAA,UAAW,KAAK,SAAS;AAAA,UAAY;AAAA,UAAQ;AAAA,UAAc;AAAA,QAClE;AAEA,cAAM,KAAK,cAAc,OAAO;AAChC,aAAK,OAAO,KAAK,0BAA0B,EAAE,UAAU,WAAW,MAAM,KAAK,SAAS,CAAC;AAAA,MACzF;AAAA,IACF,SAAS,KAAK;AACZ,WAAK,OAAO,KAAK,kCAAkC,EAAE,OAAQ,IAAc,QAAQ,CAAC;AACpF,YAAM,KAAK;AAAA,QACT,qBAAqB,KAAK,WAAW,WAAW;AAAA,MAClD;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,eAAe,UAAkB,UAAiC;AACxE,UAAM,UAAUA,MAAK,KAAK,KAAK,KAAK,SAAS,gBAAgB,SAAS,QAAQ,EAAE;AAChF,UAAM,WAAWA,MAAK,KAAK,SAAS,QAAQ;AAC5C,QAAI,CAACC,IAAG,WAAW,QAAQ,EAAG,QAAO;AACrC,QAAI;AACF,aAAOA,IAAG,aAAa,UAAU,OAAO;AAAA,IAC1C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAgB,oBAAoB,KAAmB,WAAkC;AACvF,UAAM,cAAc,KAAK,eAAe,GAAG;AAC3C,QAAI,YAAY,WAAW,EAAG;AAE9B,UAAM,UAAUD,MAAK,KAAK,KAAK,KAAK,SAAS,gBAAgB,SAAS,SAAS,EAAE;AACjF,UAAM,UAAoB,CAAC;AAE3B,eAAW,QAAQ,aAAa;AAC9B,YAAM,WAAWA,MAAK,KAAK,SAAS,KAAK,QAAQ;AACjD,UAAI,CAACC,IAAG,WAAW,QAAQ,GAAG;AAC5B,gBAAQ,KAAK,KAAK,QAAQ;AAC1B;AAAA,MACF;AACA,YAAM,OAAOA,IAAG,SAAS,QAAQ;AACjC,UAAI,KAAK,OAAO,WAAU,oBAAoB;AAC5C,gBAAQ,KAAK,GAAG,KAAK,QAAQ,KAAK,KAAK,IAAI,mCAAe;AAAA,MAC5D;AAAA,IACF;AAEA,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAM,MAAM,4FAAsB,QAAQ,KAAK,IAAI,CAAC;AACpD,WAAK,OAAO,MAAM,KAAK,EAAE,OAAO,KAAK,WAAW,UAAU,CAAC;AAC3D,YAAM,IAAI,iBAAiB,KAAK,WAAW,KAAK,EAAE,QAAQ,IAAI,UAAU,EAAE,CAAC;AAAA,IAC7E;AAAA,EACF;AAAA,EAEA,MAAc,gBAAgB,KAAmB,WAAkC;AACjF,QAAI,MAAM,KAAK,IAAI,WAAW,GAAG;AAC/B,YAAM,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC;AACxB,YAAM,KAAK,IAAI,OAAO,gBAAgB,KAAK,SAAS,+BAA+B,SAAS,EAAE;AAC9F,YAAM,KAAK,IAAI,KAAK,IAAI,UAAU;AAAA,IACpC;AAAA,EACF;AACF;;;AGjTA,OAAOC,SAAQ;AACf,OAAOC,WAAU;;;AC4BjB,IAAM,eAAe;AACrB,IAAM,gBAAgB;AACtB,IAAM,eAAe;AAGrB,IAAM,kBAAkB;AAGxB,IAAM,oBAAoB;AAEnB,IAAM,qBAAN,MAAyB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM9B,MAAM,eAA2C;AAC/C,UAAM,aAAa,CAAC,aAAa,KAAK,aAAa;AACnD,UAAM,cAAc,CAAC,cAAc,KAAK,aAAa;AACrD,UAAM,aAAa,CAAC,aAAa,KAAK,aAAa;AAEnD,UAAM,gBAAgB,KAAK,mBAAmB,aAAa;AAC3D,UAAM,mBAAmB,gBACrB,cAAc,UAAU,KAAK,cAAc,cAAc,cAAc,QACvE;AAEJ,UAAM,iBAA2B,CAAC;AAClC,QAAI,CAAC,WAAY,gBAAe,KAAK,+BAAW;AAChD,QAAI,CAAC,YAAa,gBAAe,KAAK,gCAAY;AAClD,QAAI,CAAC,WAAY,gBAAe,KAAK,gCAAO;AAC5C,QAAI,CAAC,kBAAkB;AACrB,YAAM,YAAY,gBACd,IAAI,cAAc,SAAS,IAAI,cAAc,KAAK,MAClD;AACJ,qBAAe,KAAK,0CAAiB,SAAS,EAAE;AAAA,IAClD;AAGA,UAAM,gBAAgB,gBAAgB,KAAK,aAAa;AACxD,QAAI,eAAe,WAAW,KAAK,eAAe;AAChD,qBAAe,KAAK,oEAAa;AAAA,IACnC;AAEA,UAAM,SAAS,eAAe,WAAW;AAEzC,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,eAAe,iBAAiB;AAAA,MAChC;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,sBAAsB,aAAoC;AACxD,UAAM,cAAc;AACpB,UAAM,gBAAgB;AAEtB,UAAM,mBAAmB,YAAY,MAAM,WAAW;AACtD,UAAM,qBAAqB,YAAY,MAAM,aAAa;AAE1D,UAAM,YAAY,kBAAkB,UAAU;AAC9C,UAAM,cAAc,oBAAoB,UAAU;AAElD,WAAO;AAAA,MACL;AAAA,MACA,OAAO,YAAY;AAAA,IACrB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,mBAAmB,eAA6C;AACtE,UAAM,QAAQ,cAAc,MAAM,iBAAiB;AACnD,QAAI,OAAO;AACT,aAAO;AAAA,QACL,WAAW,SAAS,MAAM,CAAC,GAAG,EAAE;AAAA,QAChC,OAAO,SAAS,MAAM,CAAC,GAAG,EAAE;AAAA,MAC9B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;;;AD/GA,SAAS,iBAAyB;AAChC,SAAO,WAAW;AACpB;AAMO,IAAM,cAAN,cAA0B,UAAU;AAAA,EAChC,YAAY;AAAA,EACJ,eAAe,IAAI,mBAAmB;AAAA,EAE7C,eAAe,KAAoB;AAC3C,UAAM,WAAW,KAAK,iBAAiB,cAAc,wBAAwB;AAC7E,WAAO,CAAC,EAAE,UAAU,OAAO,2BAAO,CAAC;AAAA,EACrC;AAAA,EAEA,MAAM,QAAQ,KAA6C;AACzD,UAAM,SAAS,MAAM,MAAM,QAAQ,GAAG;AAGtC,QAAI,OAAO,SAAS;AAClB,YAAM,SAAS,KAAK,iBAAiB,GAAG;AACxC,UAAI,QAAQ;AACV,cAAM,SAAS,KAAK,aAAa,MAAM,MAAM;AAG7C,YAAI,KAAK,OAAO,cAAc,wBAAwB,CAAC,OAAO,eAAe;AAC3E,gBAAM,cAAc,KAAK,aAAa,GAAG;AACzC,cAAI,aAAa;AACf,kBAAM,YAAY,KAAK,aAAa,sBAAsB,WAAW;AACrE,gBAAI,UAAU,QAAQ,GAAG;AACvB,qBAAO,gBAAgB;AACvB,qBAAO,mBAAmB,UAAU,cAAc,UAAU;AAC5D,kBAAI,CAAC,OAAO,kBAAkB;AAC5B,uBAAO,eAAe;AAAA,kBACpB,2CAAkB,UAAU,SAAS,IAAI,UAAU,KAAK;AAAA,gBAC1D;AACA,uBAAO,SAAS;AAAA,cAClB;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAEA,aAAK,OAAO,KAAK,wBAAwB;AAAA,UACvC,QAAQ,OAAO;AAAA,UACf,YAAY,OAAO;AAAA,UACnB,aAAa,OAAO;AAAA,UACpB,YAAY,OAAO;AAAA,UACnB,kBAAkB,OAAO;AAAA,UACzB,eAAe,OAAO;AAAA,UACtB,cAAc,OAAO,eAAe;AAAA,QACtC,CAAC;AAED,eAAO,EAAE,GAAG,QAAQ,cAAc,OAAO;AAAA,MAC3C;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEU,YAAY,KAA2B;AAC/C,UAAM,KAAK,sBAAsB,IAAI,MAAM;AAC3C,UAAM,YAAY;AAAA,MAChB,YAAY,GAAG;AAAA,MACf,kBAAkB,GAAG;AAAA,MACrB,UAAU,OAAO,GAAG,SAAS;AAAA,IAC/B;AACA,UAAM,OAAO,IAAI,iBAAiB,cAC9B,qBAAqB,SAAS,IAC9B,aAAa,SAAS;AAE1B,QAAI,CAAC,KAAK,MAAM,aAAa,GAAG;AAC9B,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,IAAI,QACjB;AAAA,MACE,aAAa,IAAI,MAAM;AAAA,MACvB,cAAc,IAAI,MAAM;AAAA,MACxB,MAAM,KAAK,OAAO,QAAQ,QAAQ,eAAe;AAAA,IACnD,IACA;AAEJ,WAAO,OAAO,sBAAsB,WAAW,QAAQ;AAAA,EACzD;AAAA,EAEQ,iBAAiB,KAAkC;AACzD,UAAM,QAAQ,KAAK,eAAe,GAAG;AACrC,QAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,UAAM,YAAY,OAAO,IAAI,OAAO,UAAU,SAAS;AACvD,UAAM,UAAUC,MAAK,KAAK,KAAK,KAAK,SAAS,gBAAgB,SAAS,SAAS,EAAE;AACjF,UAAM,WAAWA,MAAK,KAAK,SAAS,MAAM,CAAC,EAAE,QAAQ;AAErD,QAAI,CAACC,IAAG,WAAW,QAAQ,EAAG,QAAO;AACrC,QAAI;AACF,aAAOA,IAAG,aAAa,UAAU,OAAO;AAAA,IAC1C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEQ,aAAa,KAAkC;AACrD,UAAM,YAAY,OAAO,IAAI,OAAO,UAAU,SAAS;AACvD,UAAM,UAAUD,MAAK,KAAK,KAAK,KAAK,SAAS,gBAAgB,SAAS,SAAS,EAAE;AACjF,UAAM,WAAWA,MAAK,KAAK,SAAS,YAAY;AAEhD,QAAI,CAACC,IAAG,WAAW,QAAQ,EAAG,QAAO;AACrC,QAAI;AACF,aAAOA,IAAG,aAAa,UAAU,OAAO;AAAA,IAC1C,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF;AACF;;;AEvHO,IAAM,YAAN,cAAwB,UAAU;AAAA,EAC9B,YAAY;AAAA,EAEX,iBAAiB;AACzB,WAAO,CAAC,EAAE,UAAU,cAAc,OAAO,2BAAO,CAAC;AAAA,EACnD;AAAA,EAEU,aAA2C;AACnD,WAAO;AAAA,EACT;AAAA,EAEU,YAAY,KAA2B;AAC/C,UAAM,KAAK,sBAAsB,IAAI,MAAM;AAC3C,UAAM,UAAU,KAAK,KAAK,kBAAkB;AAC5C,UAAM,YAAY;AAAA,MAChB,YAAY,GAAG;AAAA,MACf,kBAAkB,GAAG;AAAA,MACrB,UAAU,OAAO,GAAG,SAAS;AAAA,MAC7B,gBAAgB,GAAG,kBAAkB;AAAA,IACvC;AAEA,QAAI;AACJ,QAAI,QAAQ,SAAS,GAAG;AACtB,mBAAa,aAAa,WAAW,OAAO;AAAA,IAC9C,OAAO;AACL,mBAAa,WAAW,SAAS;AAAA,IACnC;AAGA,UAAM,OAAO,sBAAsB,KAAK,OAAO,GAAG,IAAI;AACtD,QAAI,CAAC,MAAM,gBAAgB;AACzB,mBAAa,GAAG,EAAE,yBAAyB,CAAC;AAAA;AAAA,EAAO,UAAU;AAAA,IAC/D;AAEA,WAAO;AAAA,EACT;AACF;;;ACpCO,IAAM,aAAN,cAAyB,UAAU;AAAA,EAC/B,YAAY;AAAA,EAErB,MAAgB,oBAAoB,MAAoB,YAAmC;AACzF,QAAI,CAAC,MAAM,KAAK,IAAI,WAAW,GAAG;AAChC,YAAM,MAAM;AACZ,WAAK,OAAO,MAAM,KAAK,EAAE,OAAO,KAAK,UAAU,CAAC;AAChD,YAAM,IAAI,iBAAiB,KAAK,WAAW,KAAK,EAAE,QAAQ,IAAI,UAAU,EAAE,CAAC;AAAA,IAC7E;AAAA,EACF;AAAA,EAEU,YAAY,KAA2B;AAC/C,UAAM,KAAK,sBAAsB,IAAI,MAAM;AAC3C,UAAM,OAAO,YAAY;AAAA,MACvB,YAAY,GAAG;AAAA,MACf,kBAAkB,GAAG;AAAA,MACrB,UAAU,OAAO,GAAG,SAAS;AAAA,IAC/B,CAAC;AAED,QAAI,IAAI,YAAY;AAClB,aAAO,OAAO,EAAE,yBAAyB;AAAA,QACvC,WAAW,IAAI,WAAW;AAAA,QAC1B,UAAU,IAAI,WAAW,eAAe,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI;AAAA,QACjF,WAAW,IAAI,WAAW,UAAU,MAAM,GAAG,GAAI;AAAA,MACnD,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT;AACF;;;AChBA,IAAM,iBAAiB,oBAAI,IAA8B;AAGlD,SAAS,cAAc,MAAc,MAA8B;AACxE,iBAAe,IAAI,MAAM,IAAI;AAC/B;AAYA,SAAS,wBAA8B;AACrC,iBAAe,IAAI,QAAQ,SAAS;AACpC,iBAAe,IAAI,SAAS,UAAU;AACtC,iBAAe,IAAI,UAAU,WAAW;AAC1C;AAEA,sBAAsB;AAMf,SAAS,YAAY,SAAiB,MAA4B;AACvE,QAAM,OAAO,eAAe,IAAI,IAAI;AACpC,MAAI,CAAC,MAAM;AACT,UAAM,IAAI,wBAAwB,MAAM,CAAC,GAAG,eAAe,KAAK,CAAC,CAAC;AAAA,EACpE;AACA,SAAO,IAAI,KAAK,GAAG,IAAI;AACzB;AAGO,SAAS,sBAAsB,YAA4B;AAChE,QAAM,UAAU,WAAW,OAAO,UAAQ,CAAC,eAAe,IAAI,IAAI,CAAC;AACnE,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,IAAI,wBAAwB,SAAS,CAAC,GAAG,eAAe,KAAK,CAAC,CAAC;AAAA,EACvE;AACF;;;AChDO,IAAM,yBAAN,MAA6B;AAAA;AAAA,EAEjB;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EAEjB,YAAY,KAAkB;AAC5B,SAAK,MAAM;AACX,SAAK,gBAAgB,oBAAI,IAAI;AAC7B,SAAK,gBAAgB,oBAAI,IAAI;AAC7B,SAAK,iBAAiB,oBAAI,IAAI;AAE9B,SAAK,cAAc,GAAG;AAAA,EACxB;AAAA,EAEQ,cAAc,KAAwB;AAE5C,SAAK,oCAA+B,QAAQ,MAAM;AAClD,SAAK,oCAA+B,QAAQ,SAAS;AACrD,SAAK,iDAAqC,QAAQ,OAAO;AACzD,SAAK,kCAA8B,QAAQ,QAAQ;AACnD,SAAK,yDAAyC,YAAY,SAAS;AAGnE,eAAW,QAAQ,IAAI,QAAQ;AAC7B,WAAK,eAAe,IAAI,KAAK,MAAM;AAAA,QACjC,YAAY,KAAK;AAAA,QACjB,WAAW,KAAK;AAAA,QAChB,eAAe,KAAK;AAAA,MACtB,CAAC;AAED,UAAI,KAAK,SAAS,MAAM;AAItB,YAAI,KAAK,mDAAwC;AAC/C,eAAK,WAAW,KAAK,YAAY,KAAK,MAAM,SAAS;AAAA,QACvD;AACA,YAAI,KAAK,2CAAoC;AAC3C,eAAK,WAAW,KAAK,WAAW,KAAK,MAAM,MAAM;AAAA,QACnD,WAAW,KAAK,4CAAoC;AAClD,eAAK,WAAW,KAAK,WAAW,KAAK,MAAM,OAAO;AAAA,QACpD;AAAA,MACF,WAAW,KAAK,SAAS,QAAQ;AAG/B,YAAI,KAAK,mDAAwC;AAC/C,eAAK,WAAW,KAAK,YAAY,KAAK,MAAM,SAAS;AAAA,QACvD;AACA,YAAI,KAAK,iBAAiB,KAAK,wDAA4C;AACzE,eAAK,WAAW,KAAK,eAAe,KAAK,MAAM,OAAO;AAAA,QACxD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,WAAW,OAAmB,QAAgB,QAA4B;AAEhF,QAAI,CAAC,KAAK,cAAc,IAAI,KAAK,GAAG;AAClC,WAAK,cAAc,IAAI,OAAO,EAAE,QAAQ,OAAO,CAAC;AAAA,IAClD;AACA,UAAM,MAAM,GAAG,MAAM,IAAI,MAAM;AAC/B,QAAI,CAAC,KAAK,cAAc,IAAI,GAAG,GAAG;AAChC,WAAK,cAAc,IAAI,KAAK,KAAK;AAAA,IACnC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,QAAQ,OAAmB,cAAoC;AAE7D,QAAI,gDAAqC,cAAc;AACrD,aAAO,EAAE,QAAQ,cAAc,QAAQ,UAAU;AAAA,IACnD;AACA,QAAI,0CAAkC,cAAc;AAClD,aAAO,EAAE,QAAQ,cAAc,QAAQ,QAAQ;AAAA,IACjD;AACA,QAAI,gDAAqC,cAAc;AACrD,aAAO,EAAE,QAAQ,cAAc,QAAQ,UAAU;AAAA,IACnD;AACA,QAAI,kDAAsC,cAAc;AACtD,aAAO,EAAE,QAAQ,cAAc,QAAQ,QAAQ;AAAA,IACjD;AAEA,UAAM,SAAS,KAAK,cAAc,IAAI,KAAK;AAC3C,QAAI,OAAQ,QAAO;AAEnB,WAAO,EAAE,QAAQ,QAAQ,QAAQ,OAAO;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,QAAgB,QAA8C;AACzE,WAAO,KAAK,cAAc,IAAI,GAAG,MAAM,IAAI,MAAM,EAAE;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,OAA4B;AACrC,UAAM,KAAK,KAAK,QAAQ,KAAK;AAC7B,WAAO,GAAG,WAAW,UAAU,GAAG,WAAW,YAAY,GAAG,WAAW;AAAA,EACzE;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,OAA4B;AACvC,QAAI,6CAAmC,QAAO;AAC9C,WAAO,KAAK,QAAQ,KAAK,EAAE,WAAW;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,UAAU,OAA4B;AACpC,QAAI,6CAAmC,QAAO;AAC9C,WAAO,KAAK,QAAQ,KAAK,EAAE,WAAW;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAYA,WAAW,OAAmB,UAAkB,YAA6B;AAE3E,QAAI,uCAAgC,QAAO;AAE3C,QAAI,+CAAoC,QAAO;AAE/C,QAAI,6CAAmC,QAAO;AAE9C,QAAI,6CAAmC,QAAO;AAC9C,UAAM,KAAK,KAAK,QAAQ,KAAK;AAC7B,YAAQ,GAAG,QAAQ;AAAA,MACjB,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO,WAAW;AAAA,MACpB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AACH,eAAO;AAAA,IACX;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,0BAA0B,cAA0B,eAA4B,cAA+B;AAC7G,UAAM,SAAS,iBAAiB;AAChC,UAAM,SAAS,KAAK,IAAI;AAGxB,SAAK,iDAAsC,4CAAoC,cAAc;AAC3F,YAAM,MAAM,OAAO,UAAU,OAAK,EAAE,SAAS,YAAY;AACzD,UAAI,OAAO,GAAG;AACZ,eAAO,0CAAkC,MAAM,IAAI;AAAA,MACrD;AAAA,IACF;AACA,SAAK,iDAAsC,oDAAwC,cAAc;AAC/F,YAAM,MAAM,OAAO,UAAU,OAAK,EAAE,SAAS,YAAY;AACzD,UAAI,OAAO,GAAG;AACZ,eAAO,kDAAsC,MAAM,IAAI;AAAA,MACzD;AAAA,IACF;AAEA,aAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,YAAM,OAAO,OAAO,CAAC;AAErB,UAAI,KAAK,SAAS,UAAU,KAAK,kBAAkB,QAAQ;AACzD,eAAO,IAAI;AAAA,MACb;AAEA,UAAI,KAAK,eAAe,UAAU,KAAK,cAAc,QAAQ;AAC3D,eAAO,KAAK,cAAc,SAAS,IAAI,IAAI;AAAA,MAC7C;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,iBAAiB,WAA2C;AAC1D,UAAM,SAAS,KAAK,IAAI;AACxB,UAAM,MAAM,OAAO,UAAU,OAAK,EAAE,SAAS,SAAS;AACtD,QAAI,MAAM,EAAG,QAAO;AACpB,QAAI,QAAQ,EAAG;AACf,UAAM,OAAO,OAAO,MAAM,CAAC;AAC3B,WAAO,KAAK,iBAAiB,KAAK;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,WAA8G;AAC3H,WAAO,KAAK,eAAe,IAAI,SAAS;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,aAAa,OAAmB,cAA+B;AAC7D,SAAK,gDAAqC,2CAAmC,cAAc;AACzF,YAAM,aAAa,EAAE,kBAAkB,YAAY,EAAE;AACrD,aAAO,+CACH,EAAE,oBAAoB,EAAE,OAAO,WAAW,CAAC,IAC3C,EAAE,mBAAmB,EAAE,OAAO,WAAW,CAAC;AAAA,IAChD;AACA,SAAK,gDAAqC,mDAAuC,cAAc;AAC7F,YAAM,aAAa,EAAE,kBAAkB,YAAY,EAAE;AACrD,aAAO,+CACH,EAAE,sBAAsB,EAAE,OAAO,WAAW,CAAC,IAC7C,EAAE,uBAAuB,EAAE,OAAO,WAAW,CAAC;AAAA,IACpD;AACA,UAAM,SAAS,KAAK,mBAAmB;AACvC,WAAO,OAAO,IAAI,KAAK,KAAK;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,qBAA0C;AACxC,UAAM,SAAS,oBAAI,IAAoB;AACvC,WAAO,6BAAwB,EAAE,eAAe,CAAC;AACjD,WAAO,6BAAwB,EAAE,eAAe,CAAC;AACjD,WAAO,0CAA8B,EAAE,qBAAqB,CAAC;AAE7D,eAAW,SAAS,KAAK,IAAI,QAAQ;AACnC,YAAM,aAAa,EAAE,kBAAkB,MAAM,IAAI,EAAE;AAGnD,UAAI,MAAM,mDAAwC;AAChD,eAAO,IAAI,iBAAiB,MAAM,IAAI,IAAI,EAAE,oBAAoB,EAAE,OAAO,WAAW,CAAC,CAAC;AAAA,MACxF,WAAW,MAAM,mDAAwC;AAEvD,eAAO,IAAI,iBAAiB,MAAM,IAAI,IAAI,EAAE,sBAAsB,EAAE,OAAO,WAAW,CAAC,CAAC;AAAA,MAC1F,OAAO;AACL,eAAO,IAAI,MAAM,YAAY,EAAE,oBAAoB,EAAE,OAAO,WAAW,CAAC,CAAC;AAAA,MAC3E;AAEA,UAAI,MAAM,4CAAoC;AAC5C,eAAO,IAAI,cAAc,MAAM,IAAI,IAAI,EAAE,mBAAmB,EAAE,OAAO,WAAW,CAAC,CAAC;AAAA,MACpF,WAAW,MAAM,oDAAwC;AAEvD,eAAO,IAAI,kBAAkB,MAAM,IAAI,IAAI,EAAE,uBAAuB,EAAE,OAAO,WAAW,CAAC,CAAC;AAAA,MAC5F,WAAW,MAAM,2CAAoC;AACnD,eAAO,IAAI,MAAM,WAAW,EAAE,mBAAmB,EAAE,OAAO,WAAW,CAAC,CAAC;AAAA,MACzE;AAGA,UAAI,MAAM,iBACH,MAAM,0DACN,MAAM,kBAAkB,MAAM,WAAW;AAC9C,eAAO,IAAI,MAAM,eAAe,EAAE,uBAAuB,EAAE,OAAO,WAAW,CAAC,CAAC;AAAA,MACjF;AAAA,IACF;AAEA,WAAO,iCAA0B,EAAE,iBAAiB,CAAC;AACrD,WAAO,2BAAuB,EAAE,cAAc,CAAC;AAC/C,WAAO,kDAAkC,EAAE,yBAAyB,CAAC;AACrE,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,oBAAoB,cAAsB,cAAgF;AACxH,UAAM,SAAkE,CAAC;AACzE,QAAI,gBAAgB;AAGpB,SAAK,uDAA4C,kDAA0C,cAAc;AACvG,iBAAW,SAAS,KAAK,IAAI,QAAQ;AACnC,YAAI,eAAe;AACjB,iBAAO,MAAM,IAAI,IAAI;AAAA,QACvB,WAAW,MAAM,SAAS,cAAc;AACtC,iBAAO,MAAM,IAAI,IAAI,sDAA2C,gBAAgB;AAChF,0BAAgB;AAEhB,cAAI,8CAAuC,iBAAgB;AAAA,QAC7D,OAAO;AACL,iBAAO,MAAM,IAAI,IAAI;AAAA,QACvB;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAGA,SAAK,uDAA4C,0DAA8C,cAAc;AAC3G,iBAAW,SAAS,KAAK,IAAI,QAAQ;AACnC,YAAI,eAAe;AACjB,iBAAO,MAAM,IAAI,IAAI;AAAA,QACvB,WAAW,MAAM,SAAS,cAAc;AACtC,iBAAO,MAAM,IAAI,IAAI,sDAA2C,gBAAgB;AAChF,0BAAgB;AAAA,QAClB,OAAO;AACL,iBAAO,MAAM,IAAI,IAAI;AAAA,QACvB;AAAA,MACF;AACA,aAAO;AAAA,IACT;AAGA,QAAI,gDAAyC,+DAA+C;AAC1F,iBAAW,SAAS,KAAK,IAAI,QAAQ;AACnC,eAAO,MAAM,IAAI,IAAI;AAAA,MACvB;AACA,aAAO;AAAA,IACT;AAGA,eAAW,SAAS,KAAK,IAAI,QAAQ;AACnC,UAAI,eAAe;AACjB,eAAO,MAAM,IAAI,IAAI;AACrB;AAAA,MACF;AACA,UAAI,MAAM,eAAe,cAAc;AACrC,eAAO,MAAM,IAAI,IAAI;AACrB,wBAAgB;AAAA,MAClB,WAAW,MAAM,cAAc,gBAAgB,MAAM,kBAAkB,cAAc;AACnF,eAAO,MAAM,IAAI,IAAI;AAAA,MACvB,OAAO;AAEL,eAAO,MAAM,IAAI,IAAI;AAAA,MACvB;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,qBAA+B;AAC7B,WAAO,KAAK,IAAI,OACb,OAAO,UAAQ,KAAK,aAAc,KAAK,SAAS,IAAK,EACrD,IAAI,UAAQ,KAAK,IAAI;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,YAAY,WAA4B;AACtC,UAAM,OAAO,KAAK,IAAI,OAAO,KAAK,OAAK,EAAE,SAAS,SAAS;AAC3D,QAAI,CAAC,KAAM,QAAO;AAClB,WAAO,KAAK,aAAc,KAAK,SAAS;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,eAAsC;AACpC,WAAO,KAAK,IAAI,OAAO,KAAK,OAAK,EAAE,SAAS,MAAM;AAAA,EACpD;AAAA;AAAA;AAAA;AAAA,EAKA,oBAAoB,WAA4B;AAC9C,UAAM,OAAO,KAAK,IAAI,OAAO,KAAK,OAAK,EAAE,SAAS,SAAS;AAC3D,WAAO,MAAM,kBAAkB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,mBAAmC;AACjC,WAAO,KAAK,IAAI,OAAO,QAAQ,UAAQ,KAAK,aAAa,CAAC,CAAC;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA,EAKA,eAAkD;AAChD,WAAO,KAAK,IAAI,OAAO,IAAI,QAAM,EAAE,MAAM,EAAE,MAAM,OAAO,EAAE,MAAM,EAAE;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA,EAKA,0BAAoC;AAClC,WAAO,KAAK,IAAI,OACb,OAAO,UAAQ,KAAK,SAAS,IAAI,EACjC,IAAI,UAAQ,KAAK,IAAI;AAAA,EAC1B;AACF;;;AC5YA,IAAM,mBAAmB,oBAAI,IAAyB;AAM/C,SAAS,iBACd,KACA,QACM;AACN,mBAAiB,IAAI,IAAI,MAAM,GAAG;AAClC,MAAI,QAAQ;AACV,eAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjD,oBAAc,MAAM,IAAI;AAAA,IAC1B;AAAA,EACF;AACF;AAGO,SAAS,qBAA+B;AAC7C,SAAO,CAAC,GAAG,iBAAiB,KAAK,CAAC;AACpC;AAGO,SAAS,qBAAoC;AAClD,SAAO,CAAC,GAAG,iBAAiB,OAAO,CAAC;AACtC;AAYO,IAAM,qBAAkC;AAAA,EAC7C,MAAM;AAAA,EACN,QAAQ;AAAA,IACN;AAAA,MAAE,MAAM;AAAA,MAAQ,OAAO;AAAA,MAAM;AAAA,MAC3B;AAAA,MAAiC,MAAM;AAAA,MACvC,WAAW,CAAC,EAAE,UAAU,cAAc,OAAO,4BAAQ,UAAU,KAAK,CAAC;AAAA,IAAE;AAAA,IACzE;AAAA,MAAE,MAAM;AAAA,MAAU,OAAO;AAAA,MAAM;AAAA,MAC7B;AAAA,MAAqC;AAAA,MACrC,MAAM;AAAA,MAAQ,WAAW;AAAA,MACzB,WAAW;AAAA,QACT,EAAE,UAAU,sBAAsB,OAAO,4BAAQ,UAAU,MAAM;AAAA,QACjE,EAAE,UAAU,uBAAuB,OAAO,4BAAQ,UAAU,MAAM;AAAA,MACpE;AAAA,IAAE;AAAA,IACJ;AAAA,MAAE,MAAM;AAAA,MAAS,OAAO;AAAA,MAAM;AAAA,MAC5B;AAAA,MAAiC,MAAM;AAAA,MAAM,gBAAgB;AAAA,IAAK;AAAA,IACpE;AAAA,MAAE,MAAM;AAAA,MAAU,OAAO;AAAA,MAAM;AAAA,MAC7B;AAAA,MAAiC,MAAM;AAAA,MACvC,WAAW,CAAC,EAAE,UAAU,uBAAuB,OAAO,4BAAQ,UAAU,MAAM,CAAC;AAAA,IAAE;AAAA,EACrF;AACF;AAGA,iBAAiB,IAAI,mBAAmB,MAAM,kBAAkB;AAMzD,SAAS,oBAAoB,QAAgB,UAAiC;AACnF,MAAI,YAAY,iBAAiB,IAAI,QAAQ,EAAG,QAAO;AACvD,SAAO;AACT;AAEO,SAAS,eAAe,MAAiC;AAC9D,QAAM,MAAM,iBAAiB,IAAI,IAAI;AACrC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,sBAAsB,IAAI;AAAA,EACtC;AACA,SAAO;AACT;AAKO,SAAS,uBAAuB,KAA0C;AAC/E,SAAO,IAAI,uBAAuB,GAAG;AACvC;;;AC3HA,OAAOC,WAAU;AACjB,OAAOC,SAAQ;AACf,SAAS,gBAAgB;AACzB,SAAS,iBAAiB;;;ACOnB,SAAS,0BACd,OACA,YACY;AACZ,SAAO;AAAA,IACL,UAAU,MAAM,MAAM,GAAG;AAAA,IACzB,WAAW;AAAA,MACT,QAAQ;AAAA,MACR,YAAY,OAAO,MAAM,EAAE;AAAA,MAC3B,WAAW,OAAO,MAAM,GAAG;AAAA,IAC7B;AAAA,IACA,OAAO,MAAM;AAAA,IACb,aAAa,MAAM,eAAe;AAAA,IAClC,YAAY,aAAa,cAAc,UAAU,IAAI;AAAA,IACrD,WAAW,MAAM,eAAc,oBAAI,KAAK,GAAE,YAAY;AAAA,EACxD;AACF;AAEA,SAAS,cAAc,GAA6C;AAClE,QAAM,SAA6C,CAAC;AACpD,MAAI,EAAE,cAAc,KAAK,EAAG,QAAO,eAAe,EAAE,aAAa,KAAK;AACtE,MAAI,EAAE,oBAAoB,KAAK,EAAG,QAAO,qBAAqB,EAAE,mBAAmB,KAAK;AACxF,MAAI,EAAE,OAAO,KAAK,EAAG,QAAO,QAAQ,EAAE,MAAM,KAAK;AACjD,MAAI,EAAE,aAAa,KAAK,EAAG,QAAO,cAAc,EAAE,YAAY,KAAK;AACnE,MAAI,EAAE,YAAY,KAAK,EAAG,QAAO,aAAa,EAAE,WAAW,KAAK;AAChE,MAAI,EAAE,UAAU,KAAK,EAAG,QAAO,WAAW,EAAE,SAAS,KAAK;AAC1D,MAAI,EAAE,QAAQ,KAAK,EAAG,QAAO,SAAS,EAAE,OAAO,KAAK;AACpD,SAAO,OAAO,KAAK,MAAM,EAAE,SAAS,IAAI,SAAS;AACnD;;;ACtCA,OAAOC,SAAQ;AACf,OAAOC,WAAU;AAGjB,IAAM,gBAAgB;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,cAAc,MAA6B;AACzD,aAAW,WAAW,eAAe;AACnC,UAAM,QAAQ,KAAK,MAAM,OAAO;AAChC,QAAI,MAAO,QAAO,MAAM,CAAC;AAAA,EAC3B;AACA,SAAO;AACT;AAEO,SAAS,gBAAgB,UAAkB,YAAoB,QAAgC;AACpG,QAAM,OAAO,SAAS,QAAQ,MAAM,UAAU;AAC9C,MAAI,QAAQ;AACV,WAAO,GAAG,IAAI,YAAY,MAAM;AAAA,EAClC;AACA,SAAO;AACT;AAEO,SAAS,sBAAsB,SAM3B;AACT,QAAM,EAAE,UAAU,YAAY,kBAAkB,YAAY,QAAQ,IAAI;AAExE,QAAM,WAAqB;AAAA,IACzB,EAAE,iBAAiB;AAAA,IACnB;AAAA,IACA,aAAa,QAAQ;AAAA,IACrB,KAAK,EAAE,UAAU,CAAC,KAAK,UAAU;AAAA,IACjC,KAAK,EAAE,WAAW,CAAC,OAAO,UAAU;AAAA,IACpC;AAAA,IACA,EAAE,qBAAqB;AAAA,IACvB;AAAA,IACA,oBAAoB,EAAE,kBAAkB;AAAA,EAC1C;AAEA,MAAI,SAAS;AACX,UAAM,eAAe;AAAA,MACnB,EAAE,UAAU,kBAAkB,OAAO,EAAE,gCAAgC,EAAE;AAAA,MACzE,EAAE,UAAU,cAAc,OAAO,EAAE,4BAA4B,EAAE;AAAA,MACjE,EAAE,UAAU,gBAAgB,OAAO,EAAE,8BAA8B,EAAE;AAAA,MACrE,EAAE,UAAU,uBAAuB,OAAO,EAAE,qCAAqC,EAAE;AAAA,MACnF,EAAE,UAAU,uBAAuB,OAAO,EAAE,qCAAqC,EAAE;AAAA,IACrF;AAEA,UAAM,eAAyB,CAAC;AAChC,eAAW,EAAE,UAAU,MAAM,KAAK,cAAc;AAC9C,YAAM,WAAWC,MAAK,KAAK,SAAS,gBAAgB,SAAS,QAAQ,IAAI,QAAQ;AACjF,UAAIC,IAAG,WAAW,QAAQ,GAAG;AAC3B,cAAM,UAAUA,IAAG,aAAa,UAAU,OAAO;AACjD,cAAM,UAAU,eAAe,OAAO;AACtC,YAAI,SAAS;AACX,uBAAa,KAAK,OAAO,KAAK;AAAA;AAAA,EAAO,OAAO,EAAE;AAAA,QAChD;AAAA,MACF;AAAA,IACF;AAEA,QAAI,aAAa,SAAS,GAAG;AAC3B,eAAS,KAAK,IAAI,EAAE,cAAc,GAAG,IAAI,GAAG,YAAY;AAAA,IAC1D;AAAA,EACF;AAEA,WAAS,KAAK,IAAI,OAAO,EAAE,gBAAgB,CAAC;AAC5C,SAAO,SAAS,KAAK,IAAI;AAC3B;AAEA,SAAS,eAAe,SAAiB,WAAW,IAAY;AAC9D,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,MAAI,MAAM,UAAU,SAAU,QAAO,QAAQ,KAAK;AAClD,SAAO,MAAM,MAAM,GAAG,QAAQ,EAAE,KAAK,IAAI,EAAE,KAAK,IAAI,SAAS,EAAE,cAAc;AAC/E;;;AClFA,OAAO,SAAS;AAIhB,IAAMC,UAAS,OAAW,MAAM,eAAe;AAa/C,IAAM,kBAAwC;AAAA,EAC5C,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,UAAU;AACZ;AAEA,SAAS,mBAAmB,MAAgC;AAC1D,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAM,SAAS,IAAI,aAAa;AAChC,WAAO,KAAK,SAAS,MAAM,QAAQ,KAAK,CAAC;AACzC,WAAO,KAAK,aAAa,MAAM;AAC7B,aAAO,MAAM,MAAM,QAAQ,IAAI,CAAC;AAAA,IAClC,CAAC;AACD,WAAO,OAAO,MAAM,SAAS;AAAA,EAC/B,CAAC;AACH;AAEO,IAAM,gBAAN,MAAoB;AAAA,EACjB,YAAY,oBAAI,IAAsB;AAAA,EACtC;AAAA,EAER,YAAY,SAAyC;AACnD,SAAK,UAAU,EAAE,GAAG,iBAAiB,GAAG,QAAQ;AAAA,EAClD;AAAA,EAEA,MAAM,SAAS,UAAqC;AAClD,UAAM,WAAW,KAAK,UAAU,IAAI,QAAQ;AAC5C,QAAI,UAAU;AACZ,MAAAA,QAAO,KAAK,qCAAqC,EAAE,UAAU,OAAO,SAAS,CAAC;AAC9E,aAAO;AAAA,IACT;AAEA,UAAM,cAAc,IAAI,IAAI,CAAC,GAAG,KAAK,UAAU,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,WAAW,CAAC;AAClF,UAAM,eAAe,IAAI,IAAI,CAAC,GAAG,KAAK,UAAU,OAAO,CAAC,EAAE,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC;AAEpF,aAAS,SAAS,GAAG,UAAU,KAAK,QAAQ,UAAU,UAAU;AAC9D,YAAM,cAAc,KAAK,QAAQ,kBAAkB;AACnD,YAAM,eAAe,KAAK,QAAQ,mBAAmB;AAErD,UAAI,YAAY,IAAI,WAAW,KAAK,aAAa,IAAI,YAAY,GAAG;AAClE;AAAA,MACF;AAEA,YAAM,CAAC,MAAM,IAAI,IAAI,MAAM,QAAQ,IAAI;AAAA,QACrC,mBAAmB,WAAW;AAAA,QAC9B,mBAAmB,YAAY;AAAA,MACjC,CAAC;AAED,UAAI,QAAQ,MAAM;AAChB,cAAM,OAAiB,EAAE,aAAa,aAAa;AACnD,aAAK,UAAU,IAAI,UAAU,IAAI;AACjC,QAAAA,QAAO,KAAK,mBAAmB,EAAE,UAAU,GAAG,KAAK,CAAC;AACpD,eAAO;AAAA,MACT;AAEA,MAAAA,QAAO,MAAM,sCAAsC;AAAA,QACjD;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAEA,UAAM,IAAI;AAAA,MACR,2CAA2C,QAAQ,aACvC,KAAK,QAAQ,QAAQ,yBACtB,KAAK,QAAQ,eAAe,aAAa,KAAK,QAAQ,gBAAgB;AAAA,IACnF;AAAA,EACF;AAAA,EAEA,QAAQ,UAAwB;AAC9B,UAAM,OAAO,KAAK,UAAU,IAAI,QAAQ;AACxC,QAAI,MAAM;AACR,WAAK,UAAU,OAAO,QAAQ;AAC9B,MAAAA,QAAO,KAAK,kBAAkB,EAAE,UAAU,GAAG,KAAK,CAAC;AAAA,IACrD;AAAA,EACF;AAAA,EAEA,iBAAiB,UAAwC;AACvD,WAAO,KAAK,UAAU,IAAI,QAAQ;AAAA,EACpC;AAAA,EAEA,kBAAyC;AACvC,WAAO,IAAI,IAAI,KAAK,SAAS;AAAA,EAC/B;AAAA,EAEA,QAAQ,UAAkB,OAAuB;AAC/C,SAAK,UAAU,IAAI,UAAU,KAAK;AAClC,IAAAA,QAAO,KAAK,mCAAmC,EAAE,UAAU,GAAG,MAAM,CAAC;AAAA,EACvE;AACF;;;AC3GA,SAAS,aAA2B;AACpC,OAAOC,WAAU;AACjB,OAAO,WAAW;AAClB,OAAO,UAAU;AAKjB,IAAMC,UAAS,OAAW,MAAM,kBAAkB;AAiBlD,IAAMC,mBAA2C;AAAA,EAC/C,sBAAsB;AAAA,EACtB,uBAAuB;AACzB;AAEA,SAAS,YACP,MACA,QACA,WACA,YACe;AACf,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,WAAW,KAAK,IAAI,IAAI;AAE9B,UAAM,QAAQ,MAAM;AAClB,UAAI,KAAK,IAAI,IAAI,UAAU;AACzB,eAAO,IAAI,MAAM,QAAQ,IAAI,oBAAoB,SAAS,IAAI,CAAC;AAC/D;AAAA,MACF;AAEA,YAAM,MAAM,SACR,MAAM;AAAA,QACJ,EAAE,UAAU,aAAa,MAAM,MAAM,KAAK,oBAAoB,OAAO,SAAS,IAAM;AAAA,QACpF,CAAC,QAAQ;AAAE,cAAI,OAAO;AAAG,kBAAQ;AAAA,QAAG;AAAA,MACtC,IACA,KAAK;AAAA,QACH,EAAE,UAAU,aAAa,MAAM,MAAM,KAAK,SAAS,IAAM;AAAA,QACzD,CAAC,QAAQ;AAAE,cAAI,OAAO;AAAG,kBAAQ;AAAA,QAAG;AAAA,MACtC;AAEJ,UAAI,GAAG,SAAS,MAAM;AACpB,mBAAW,OAAO,UAAU;AAAA,MAC9B,CAAC;AACD,UAAI,GAAG,WAAW,MAAM;AACtB,YAAI,QAAQ;AACZ,mBAAW,OAAO,UAAU;AAAA,MAC9B,CAAC;AAAA,IACH;AAEA,UAAM;AAAA,EACR,CAAC;AACH;AAEO,IAAM,mBAAN,MAAuB;AAAA,EACpB,UAAU,oBAAI,IAAuB;AAAA,EACrC;AAAA,EAER,YAAY,SAA4C;AACtD,SAAK,UAAU,EAAE,GAAGA,kBAAiB,GAAG,QAAQ;AAAA,EAClD;AAAA,EAEA,MAAM,aAAa,OAAwB,OAAgC;AACzE,QAAI,KAAK,QAAQ,IAAI,MAAM,QAAQ,GAAG;AACpC,MAAAD,QAAO,KAAK,qCAAqC,EAAE,UAAU,MAAM,SAAS,CAAC;AAC7E;AAAA,IACF;AAEA,IAAAA,QAAO,KAAK,wBAAwB,EAAE,UAAU,MAAM,UAAU,GAAG,MAAM,CAAC;AAE1E,UAAM,aAAqC;AAAA,MACzC,GAAG,QAAQ;AAAA,MACX,MAAM,OAAO,MAAM,WAAW;AAAA,MAC9B,mBAAmB;AAAA,MACnB,UAAU;AAAA,IACZ;AAEA,UAAM,aAAa,KAAK,QAAQ,kBAAkB,EAAE,KAAK,QAAQ,MAAM,CAAC,OAAO,SAAS,SAAS,EAAE;AACnG,UAAM,UAAU,MAAM,WAAW,KAAK,WAAW,MAAM;AAAA,MACrD,KAAK,MAAM;AAAA,MACX,KAAK;AAAA,MACL,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,MAChC,UAAU;AAAA,IACZ,CAAC;AAED,YAAQ,QAAQ,GAAG,QAAQ,CAAC,SAAiB;AAC3C,MAAAA,QAAO,MAAM,QAAQ,MAAM,QAAQ,KAAK,KAAK,SAAS,EAAE,QAAQ,CAAC,EAAE;AAAA,IACrE,CAAC;AACD,YAAQ,QAAQ,GAAG,QAAQ,CAAC,SAAiB;AAC3C,MAAAA,QAAO,MAAM,QAAQ,MAAM,QAAQ,SAAS,KAAK,SAAS,EAAE,QAAQ,CAAC,EAAE;AAAA,IACzE,CAAC;AACD,YAAQ,GAAG,QAAQ,CAAC,SAAS;AAC3B,MAAAA,QAAO,KAAK,0BAA0B,EAAE,UAAU,MAAM,UAAU,KAAK,CAAC;AAAA,IAC1E,CAAC;AAED,UAAM,cAAcE,MAAK,KAAK,MAAM,SAAS,UAAU;AACvD,UAAM,cAAsC;AAAA,MAC1C,GAAG,QAAQ;AAAA,MACX,cAAc,OAAO,MAAM,WAAW;AAAA,MACtC,eAAe,OAAO,MAAM,YAAY;AAAA,IAC1C;AAEA,UAAM,cAAc,KAAK,QAAQ,mBAC5B,EAAE,KAAK,QAAQ,MAAM,CAAC,OAAO,MAAM,UAAU,OAAO,MAAM,YAAY,CAAC,EAAE;AAC9E,UAAM,WAAW,MAAM,YAAY,KAAK,YAAY,MAAM;AAAA,MACxD,KAAK;AAAA,MACL,KAAK;AAAA,MACL,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,MAChC,UAAU;AAAA,IACZ,CAAC;AAED,aAAS,QAAQ,GAAG,QAAQ,CAAC,SAAiB;AAC5C,MAAAF,QAAO,MAAM,QAAQ,MAAM,QAAQ,KAAK,KAAK,SAAS,EAAE,QAAQ,CAAC,EAAE;AAAA,IACrE,CAAC;AACD,aAAS,QAAQ,GAAG,QAAQ,CAAC,SAAiB;AAC5C,MAAAA,QAAO,MAAM,QAAQ,MAAM,QAAQ,SAAS,KAAK,SAAS,EAAE,QAAQ,CAAC,EAAE;AAAA,IACzE,CAAC;AACD,aAAS,GAAG,QAAQ,CAAC,SAAS;AAC5B,MAAAA,QAAO,KAAK,2BAA2B,EAAE,UAAU,MAAM,UAAU,KAAK,CAAC;AAAA,IAC3E,CAAC;AAED,UAAM,YAAuB;AAAA,MAC3B;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,MAAM;AAAA,MACf,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AACA,SAAK,QAAQ,IAAI,MAAM,UAAU,SAAS;AAE1C,IAAAA,QAAO,KAAK,yCAAyC,EAAE,UAAU,MAAM,SAAS,CAAC;AAEjF,QAAI;AACF,YAAM,QAAQ,IAAI;AAAA,QAChB;AAAA,UACE,MAAM;AAAA,UACN;AAAA,UACA,KAAK,QAAQ;AAAA,UACb,KAAK,QAAQ;AAAA,QACf;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN;AAAA,UACA,KAAK,QAAQ;AAAA,UACb,KAAK,QAAQ;AAAA,QACf;AAAA,MACF,CAAC;AACD,MAAAA,QAAO,KAAK,uBAAuB,EAAE,UAAU,MAAM,UAAU,GAAG,MAAM,CAAC;AAAA,IAC3E,SAAS,KAAK;AACZ,MAAAA,QAAO,MAAM,gDAAgD;AAAA,QAC3D,UAAU,MAAM;AAAA,QAChB,OAAQ,IAAc;AAAA,MACxB,CAAC;AACD,WAAK,YAAY,MAAM,QAAQ;AAC/B,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,YAAY,UAAwB;AAClC,UAAM,MAAM,KAAK,QAAQ,IAAI,QAAQ;AACrC,QAAI,CAAC,IAAK;AAEV,IAAAA,QAAO,KAAK,wBAAwB,EAAE,UAAU,OAAO,IAAI,MAAM,CAAC;AAElE,gBAAY,IAAI,SAAS,YAAY,QAAQ,EAAE;AAC/C,gBAAY,IAAI,UAAU,aAAa,QAAQ,EAAE;AAEjD,SAAK,QAAQ,OAAO,QAAQ;AAAA,EAC9B;AAAA,EAEA,UAAgB;AACd,eAAW,CAAC,GAAG,KAAK,KAAK,SAAS;AAChC,WAAK,YAAY,GAAG;AAAA,IACtB;AAAA,EACF;AAAA,EAEA,UAAU,UAA8E;AACtF,UAAM,MAAM,KAAK,QAAQ,IAAI,QAAQ;AACrC,QAAI,CAAC,IAAK,QAAO,EAAE,SAAS,MAAM;AAClC,WAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO,IAAI;AAAA,MACX,WAAW,IAAI;AAAA,IACjB;AAAA,EACF;AAAA,EAEA,mBAA6B;AAC3B,WAAO,CAAC,GAAG,KAAK,QAAQ,KAAK,CAAC;AAAA,EAChC;AACF;AAEA,SAAS,YAAY,MAAoB,OAAqB;AAC5D,MAAI;AACF,QAAI,KAAK,UAAU,KAAK,aAAa,KAAM;AAC3C,SAAK,KAAK,SAAS;AACnB,eAAW,MAAM;AACf,UAAI,CAAC,KAAK,UAAU,KAAK,aAAa,MAAM;AAC1C,QAAAA,QAAO,KAAK,iBAAiB,KAAK,EAAE;AACpC,aAAK,KAAK,SAAS;AAAA,MACrB;AAAA,IACF,GAAG,GAAK;AAAA,EACV,SAAS,KAAK;AACZ,IAAAA,QAAO,KAAK,kBAAkB,KAAK,IAAI,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,EAC1E;AACF;;;ACvNA,IAAI;AAEG,SAAS,cAAc,KAAsB;AAClD,SAAO,eAAe,IAAI,IAAI;AAChC;AAEO,SAAS,eAAe,OAAkC;AAC/D,gBAAc;AAChB;AAEO,SAAS,qBACd,UACA,SACA,KACS;AACT,QAAM,SAAS,QAAQ,IAAI,QAAQ;AACnC,MAAI,QAAQ,eAAe,OAAW,QAAO,OAAO;AACpD,SAAO,cAAc,GAAG;AAC1B;;;ACrBA,OAAOG,SAAQ;AACf,OAAOC,WAAU;AAGjB,IAAMC,UAAS,OAAW,MAAM,qBAAqB;AAErD,IAAM,kBAAkB;AAOxB,SAAS,QAAQ,KAAa,QAAkB,CAAC,GAAa;AAC5D,aAAW,SAASC,IAAG,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC,GAAG;AAChE,UAAM,OAAOC,MAAK,KAAK,KAAK,MAAM,IAAI;AACtC,QAAI,MAAM,YAAY,GAAG;AACvB,cAAQ,MAAM,KAAK;AAAA,IACrB,WAAW,MAAM,OAAO,KAAK,MAAM,KAAK,SAAS,MAAM,GAAG;AACxD,YAAM,KAAK,IAAI;AAAA,IACjB;AAAA,EACF;AACA,SAAO;AACT;AAOO,SAAS,mBAAmB,SAAmC;AACpE,QAAM,iBAAiBA,MAAK,KAAK,SAAS,YAAY,cAAc;AACpE,MAAI,CAACD,IAAG,WAAW,cAAc,GAAG;AAClC,IAAAD,QAAO,MAAM,oCAAoC,EAAE,KAAK,eAAe,CAAC;AACxE,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,WAAW,QAAQ,cAAc;AACvC,MAAI,SAAS,WAAW,GAAG;AACzB,IAAAA,QAAO,MAAM,sBAAsB;AACnC,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,cAAgC,SAAS,IAAI,CAAC,aAAa;AAC/D,UAAM,WAAWE,MAAK,SAAS,gBAAgB,QAAQ;AACvD,UAAM,WAAW,SAAS,MAAMA,MAAK,GAAG,EAAE,CAAC,KAAKA,MAAK,SAAS,UAAU,MAAM;AAC9E,WAAO,EAAE,UAAU,SAAS;AAAA,EAC9B,CAAC;AAED,MAAI,YAAY,SAAS,iBAAiB;AACxC,IAAAF,QAAO,KAAK,oCAAoC;AAAA,MAC9C,OAAO,YAAY;AAAA,MACnB,KAAK;AAAA,IACP,CAAC;AACD,WAAO,YAAY,MAAM,GAAG,eAAe;AAAA,EAC7C;AAEA,EAAAA,QAAO,KAAK,yBAAyB,EAAE,OAAO,YAAY,OAAO,CAAC;AAClE,SAAO;AACT;;;ACtDA,IAAMG,WAAS,OAAW,MAAM,qBAAqB;AAcrD,SAAS,aAAa,UAAgC,WAA4B;AAChF,QAAM,QAAkB,CAAC,EAAE,kBAAkB,GAAG,EAAE;AAElD,aAAW,QAAQ,UAAU;AAC3B,UAAM,KAAK,OAAO,KAAK,QAAQ,IAAI,IAAI,KAAK,UAAU,EAAE;AAAA,EAC1D;AAEA,MAAI,WAAW;AACb,UAAM,KAAK,EAAE,sBAAsB,GAAG,EAAE;AAAA,EAC1C;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEO,IAAM,sBAAN,MAA0B;AAAA,EAC/B,YAAoB,UAA0B;AAA1B;AAAA,EAA2B;AAAA,EAE/C,MAAM,QAAQ,SAAwC;AACpD,UAAM,EAAE,SAAS,UAAU,SAAS,MAAM,IAAI;AAE9C,UAAM,cAAc,mBAAmB,OAAO;AAC9C,QAAI,YAAY,WAAW,GAAG;AAC5B,MAAAA,SAAO,KAAK,iCAAiC,EAAE,SAAS,CAAC;AACzD;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,KAAK,UAAU,WAAW;AACjD,QAAI,SAAS,WAAW,GAAG;AACzB,MAAAA,SAAO,KAAK,iCAAiC,EAAE,SAAS,CAAC;AACzD;AAAA,IACF;AAEA,UAAM,YAAY,YAAY,UAAU;AACxC,UAAM,UAAU,aAAa,UAAU,SAAS;AAEhD,UAAM,KAAK,YAAY,SAAS,OAAO;AAEvC,QAAI,OAAO;AACT,YAAM,KAAK,mBAAmB,OAAO,OAAO;AAAA,IAC9C;AAEA,IAAAA,SAAO,KAAK,6BAA6B;AAAA,MACvC;AAAA,MACA;AAAA,MACA,OAAO,SAAS;AAAA,IAClB,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,UAAU,aAA8D;AACpF,UAAM,UAAgC,CAAC;AAEvC,eAAW,cAAc,aAAa;AACpC,UAAI;AACF,cAAM,SAAuB,MAAM,KAAK,SAAS,WAAW,WAAW,QAAQ;AAC/E,gBAAQ,KAAK;AAAA,UACX,UAAU,WAAW;AAAA,UACrB,UAAU,OAAO;AAAA,QACnB,CAAC;AAAA,MACH,SAAS,KAAK;AACZ,QAAAA,SAAO,KAAK,+BAA+B;AAAA,UACzC,UAAU,WAAW;AAAA,UACrB,OAAQ,IAAc;AAAA,QACxB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,YAAY,SAAiB,SAAgC;AACzE,QAAI;AACF,YAAM,KAAK,SAAS,gBAAgB,SAAS,OAAO;AAAA,IACtD,SAAS,KAAK;AACZ,MAAAA,SAAO,KAAK,uCAAuC;AAAA,QACjD;AAAA,QACA,OAAQ,IAAc;AAAA,MACxB,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,MAAc,mBAAmB,OAAe,SAAgC;AAC9E,QAAI;AACF,YAAM,KAAK,SAAS,uBAAuB,OAAO,OAAO;AAAA,IAC3D,SAAS,KAAK;AACZ,MAAAA,SAAO,KAAK,+CAA+C;AAAA,QACzD;AAAA,QACA,OAAQ,IAAc;AAAA,MACxB,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;AC1EA,SAAS,YAAY,QAA8B;AACjD,QAAM,QAAQ,OAAO,QAAQ,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAC1E,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,GAAG;AACtD;AAEA,SAAS,gBAAgB,KAAqB;AAC5C,SAAO,MAAM,IAAI,GAAG,MAAM;AAC5B;AAMA,IAAM,kBAAkB;AAAA,EACtB;AAAA,EAAO;AAAA,EAAM;AAAA,EAAO;AAAA,EAAM;AAAA,EAAK;AAAA,EAAM;AAAA,EAAK;AAAA,EAAG;AAAA,EAAK;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAC7E;AAMO,IAAM,mBAAN,MAAuB;AAAA,EACX,UAAU,oBAAI,IAAyB;AAAA;AAAA;AAAA,EAKxD,gBAAgB,MAAc,MAAoB;AAChD,QAAI,KAAK,QAAQ,IAAI,IAAI,EAAG;AAC5B,SAAK,QAAQ,IAAI,MAAM,EAAE,MAAM,WAAW,MAAM,QAAQ,oBAAI,IAAI,EAAE,CAAC;AAAA,EACrE;AAAA;AAAA,EAGA,WAAW,MAAc,SAAuB,CAAC,GAAG,QAAQ,GAAS;AACnE,UAAM,QAAQ,KAAK,QAAQ,IAAI,IAAI;AACnC,QAAI,CAAC,SAAS,MAAM,SAAS,UAAW;AACxC,UAAM,MAAM,YAAY,MAAM;AAC9B,UAAM,OAAO,IAAI,MAAM,MAAM,OAAO,IAAI,GAAG,KAAK,KAAK,KAAK;AAAA,EAC5D;AAAA;AAAA,EAGA,WAAW,MAAc,SAAuB,CAAC,GAAW;AAC1D,UAAM,QAAQ,KAAK,QAAQ,IAAI,IAAI;AACnC,QAAI,CAAC,SAAS,MAAM,SAAS,UAAW,QAAO;AAC/C,WAAO,MAAM,OAAO,IAAI,YAAY,MAAM,CAAC,KAAK;AAAA,EAClD;AAAA;AAAA;AAAA,EAKA,kBAAkB,MAAc,MAAc,SAA0B;AACtE,QAAI,KAAK,QAAQ,IAAI,IAAI,EAAG;AAC5B,UAAM,gBAAgB,CAAC,GAAI,WAAW,eAAgB,EAAE,KAAK,CAAC,GAAG,MAAM,IAAI,CAAC;AAC5E,SAAK,QAAQ,IAAI,MAAM,EAAE,MAAM,aAAa,MAAM,SAAS,eAAe,QAAQ,oBAAI,IAAI,EAAE,CAAC;AAAA,EAC/F;AAAA;AAAA,EAGA,iBAAiB,MAAc,OAAe,SAAuB,CAAC,GAAS;AAC7E,UAAM,QAAQ,KAAK,QAAQ,IAAI,IAAI;AACnC,QAAI,CAAC,SAAS,MAAM,SAAS,YAAa;AAC1C,UAAM,MAAM,YAAY,MAAM;AAC9B,QAAI,OAAO,MAAM,OAAO,IAAI,GAAG;AAC/B,QAAI,CAAC,MAAM;AACT,aAAO,EAAE,cAAc,IAAI,MAAM,MAAM,QAAQ,MAAM,EAAE,KAAK,CAAC,GAAG,KAAK,GAAG,OAAO,EAAE;AACjF,YAAM,OAAO,IAAI,KAAK,IAAI;AAAA,IAC5B;AACA,SAAK,OAAO;AACZ,SAAK,SAAS;AAEd,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,QAAQ,KAAK;AAC7C,UAAI,SAAS,MAAM,QAAQ,CAAC,GAAG;AAC7B,aAAK,aAAa,CAAC,KAAK;AACxB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA,EAKA,WAAW,eAAuB,SAAuB,CAAC,GAAiB;AACzE,UAAM,QAAQ,YAAY,IAAI;AAC9B,WAAO,MAAM;AACX,YAAM,WAAW,YAAY,IAAI,IAAI,SAAS;AAC9C,WAAK,iBAAiB,eAAe,SAAS,MAAM;AACpD,aAAO;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA,EAKA,YAAoB;AAClB,UAAM,QAAkB,CAAC;AAEzB,eAAW,CAAC,MAAM,KAAK,KAAK,KAAK,SAAS;AACxC,UAAI,MAAM,SAAS,WAAW;AAC5B,cAAM,KAAK,UAAU,IAAI,IAAI,MAAM,IAAI,EAAE;AACzC,cAAM,KAAK,UAAU,IAAI,UAAU;AACnC,mBAAW,CAAC,KAAK,KAAK,KAAK,MAAM,QAAQ;AACvC,gBAAM,KAAK,GAAG,IAAI,GAAG,gBAAgB,GAAG,CAAC,IAAI,KAAK,EAAE;AAAA,QACtD;AAAA,MACF,WAAW,MAAM,SAAS,aAAa;AACrC,cAAM,KAAK,UAAU,IAAI,IAAI,MAAM,IAAI,EAAE;AACzC,cAAM,KAAK,UAAU,IAAI,YAAY;AACrC,mBAAW,CAAC,KAAK,IAAI,KAAK,MAAM,QAAQ;AACtC,gBAAM,SAAS,MAAM,IAAI,GAAG,KAAK;AACjC,cAAI,aAAa;AACjB,mBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,QAAQ,KAAK;AAC7C,0BAAc,KAAK,aAAa,CAAC;AACjC,kBAAM,KAAK,GAAG,IAAI,eAAe,MAAM,QAAQ,CAAC,CAAC,IAAI,MAAM,KAAK,UAAU,EAAE;AAAA,UAC9E;AACA,gBAAM,KAAK,GAAG,IAAI,oBAAoB,MAAM,KAAK,KAAK,KAAK,EAAE;AAC7D,gBAAM,KAAK,GAAG,IAAI,OAAO,gBAAgB,GAAG,CAAC,IAAI,KAAK,GAAG,EAAE;AAC3D,gBAAM,KAAK,GAAG,IAAI,SAAS,gBAAgB,GAAG,CAAC,IAAI,KAAK,KAAK,EAAE;AAAA,QACjE;AAAA,MACF;AACA,YAAM,KAAK,EAAE;AAAA,IACf;AAEA,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAAA;AAAA,EAGA,QAAc;AACZ,eAAW,SAAS,KAAK,QAAQ,OAAO,GAAG;AACzC,UAAI,MAAM,SAAS,WAAW;AAC5B,cAAM,OAAO,MAAM;AAAA,MACrB,WAAW,MAAM,SAAS,aAAa;AACrC,cAAM,OAAO,MAAM;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AACF;AAMO,IAAM,UAAU,IAAI,iBAAiB;AAG5C,QAAQ,gBAAgB,oBAAoB,kCAAkC;AAC9E,QAAQ,gBAAgB,8BAA8B,yCAAyC;AAC/F,QAAQ,gBAAgB,2BAA2B,yBAAyB;AAC5E,QAAQ,gBAAgB,4BAA4B,yBAAyB;AAG7E,QAAQ,gBAAgB,oBAAoB,kCAAkC;AAC9E,QAAQ,gBAAgB,2BAA2B,mCAAmC;AACtF,QAAQ,kBAAkB,8BAA8B,0CAA0C;AAAA,EAChG;AAAA,EAAG;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AACxC,CAAC;AAGD,QAAQ,gBAAgB,sBAAsB,6BAA6B;AAC3E,QAAQ,gBAAgB,uBAAuB,kBAAkB;AACjE,QAAQ,kBAAkB,2BAA2B,sCAAsC;AAAA,EACzF;AAAA,EAAG;AAAA,EAAG;AAAA,EAAI;AAAA,EAAI;AAAA,EAAI;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AAAA,EAAK;AACxC,CAAC;AAGD,QAAQ,gBAAgB,+BAA+B,6BAA6B;AACpF,QAAQ,gBAAgB,6BAA6B,qBAAqB;AAC1E,QAAQ,kBAAkB,yCAAyC,4CAA4C;AAAA,EAC7G;AAAA,EAAM;AAAA,EAAK;AAAA,EAAM;AAAA,EAAK;AAAA,EAAG;AAAA,EAAK;AAAA,EAAG;AACnC,CAAC;AAGD,QAAQ,gBAAgB,8BAA8B,iCAAiC;AAGvF,QAAQ,gBAAgB,+BAA+B,yBAAyB;AAChF,QAAQ,gBAAgB,6BAA6B,uBAAuB;;;AC1M5E,IAAMC,WAAS,OAAW,MAAM,WAAW;AAY3C,eAAsB,aACpB,KACA,MACsB;AACtB,QAAM,EAAE,OAAO,OAAO,QAAQ,aAAa,WAAW,IAAI;AAG1D,MAAI;AACF,UAAM,KAAK,SAAS,kBAAkB,MAAM,IAAI;AAAA,MAC9C,GAAG,MAAM,OAAO,OAAO,OAAK,CAAC,EAAE,WAAW,cAAc,CAAC;AAAA,MACzD;AAAA,IACF,CAAC;AAAA,EACH,SAAS,KAAK;AACZ,IAAAA,SAAO,KAAK,iCAAiC,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,EAChF;AAGA,QAAM,KAAK,aAAa,aAAa,YAAY;AAC/C,SAAK,aAAa,MAAM,KAAK,SAAS,EAAE,4BAA4B,CAAC;AACrE,UAAM,KAAK,QAAQ,MAAM;AACzB,SAAK,aAAa,MAAM,KAAK,YAAY,EAAE,+BAA+B,CAAC;AAC3E,UAAM,KAAK,eAAe,KAAK;AAAA,EACjC,CAAC;AAGD,MAAI,OAAO,mCAA8B;AACvC,SAAK,QAAQ,YAAY,MAAM,yCAA6B;AAAA,EAC9D;AAGA,OAAK,aAAa,MAAM,KAAK,WAAW,EAAE,8BAA8B,CAAC;AACzE,QAAM,KAAK,oBAAoB,MAAM,OAAO;AAG5C,OAAK,aAAa,MAAM,KAAK,aAAa,EAAE,+BAA+B,CAAC;AAC5E,QAAM,QAAQ,IAAI,cAAc,MAAM,UAAU;AAChD,QAAM,SAAS,IAAI,gBAAgB,MAAM,SAAS,MAAM,GAAG;AAE3D,SAAO,UAAU;AACjB,SAAO,eAAe;AAAA,IACpB,IAAI,MAAM;AAAA,IACV,KAAK,MAAM;AAAA,IACX,OAAO,MAAM;AAAA,IACb,QAAQ,MAAM;AAAA,IACd,OAAO,MAAM;AAAA,EACf,CAAC;AAED,QAAM,mBAAmB,OAAO,aAAa;AAC7C,MAAI,CAAC,kBAAkB;AACrB,WAAO;AAAA,MACL,OAAO,sBAAsB,MAAM,KAAK,MAAM,OAAO,YAAY,WAAW;AAAA,IAC9E;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,OAAO;AACzB;;;AC/DA,IAAMC,WAAS,OAAW,MAAM,eAAe;AAa/C,eAAsB,iBACpB,KACA,MACA,OACA,QACgD;AAChD,QAAM,EAAE,OAAO,aAAa,kBAAkB,QAAQ,SAAS,SAAS,IAAI;AAE5E,QAAM,WAAW,iBAAiB;AAAA,IAChC,OAAO;AAAA,IACP,UAAU,OAAO,gBAAgB;AAAA,IACjC,OAAO;AAAA,EACT;AAEA,OAAK;AAAA,IACH,MAAM;AAAA,IACN;AAAA,IACA,EAAE,mCAAmC;AAAA,MACnC,OAAO,YAAY,OAAO,QAAQ,GAAG,QAAQ;AAAA,IAC/C,CAAC;AAAA,EACH;AAEA,QAAM,kBAAkB,KAAK,oBAAoB,MAAM,GAAG;AAC1D,MAAI,iBAAiB;AAErB,WAAS,IAAI,UAAU,IAAI,YAAY,OAAO,QAAQ,KAAK;AACzD,QAAI,eAAe,GAAG;AACpB,YAAM,IAAI,qBAAqB;AAAA,IACjC;AAEA,UAAM,OAAO,YAAY,OAAO,CAAC;AAGjC,QAAI,KAAK,SAAS,QAAQ;AACxB,UAAI,KAAK,kBAAkB,MAAM,MAAM,GAAG;AACxC,QAAAA,SAAO,KAAK,0DAA0D;AAAA,UACpE,KAAK,MAAM;AAAA,UACX,QAAQ,MAAM;AAAA,UACd,mBAAmB,KAAK,OAAO,OAAO;AAAA,QACxC,CAAC;AACD,YAAI,KAAK,eAAe;AACtB,eAAK,QAAQ,YAAY,MAAM,KAAK,KAAK,eAAe,EAAE,cAAc,KAAK,KAAK,CAAC;AAAA,QACrF;AACA,eAAO,oBAAoB,KAAK,MAAM,WAAW;AACjD,YAAI;AACF,gBAAM,KAAK,SAAS;AAAA,YAClB,MAAM;AAAA,YACN,EAAE,iCAAiC;AAAA,UACrC;AAAA,QACF,QAAQ;AAAA,QAAe;AACvB;AAAA,MACF;AAGA,WAAK,QAAQ,YAAY,MAAM,KAAK,KAAK,YAAY,EAAE,cAAc,KAAK,KAAK,CAAC;AAChF,aAAO,oBAAoB,KAAK,MAAM,aAAa;AACnD,WAAK,SAAS,UAAU,oBAAoB,EAAE,UAAU,MAAM,IAAI,CAAC;AACnE,MAAAA,SAAO,KAAK,gCAAgC,EAAE,KAAK,MAAM,IAAI,CAAC;AAC9D,aAAO,EAAE,gBAAgB,QAAQ,KAAK;AAAA,IACxC;AAGA,QAAI,KAAK,SAAS,YAAY,KAAK,OAAO,cAAc,SAAS;AAE/D,YAAM,WAAW,yBAAyB,YAAY,QAAQ,CAAC;AAC/D,YAAM,qBAAqB,KAAK,MAAM,OAAO,QAAQ,GAAG,QAAQ;AAChE;AAAA,IACF;AAGA,UAAM,QAAQ,KAAK,gBAAgB,MAAM,KAAK,MAAM,EAAE;AACtD,UAAM,QAAQ,YAAY,KAAK,MAAM,KAAK,UAAU,OAAO,QAAQ,KAAK,QAAQ,kBAAkB,KAAK;AACvG,UAAM,MAAM,QAAQ,QAAQ;AAG5B,QAAI,mBAAmB,CAAC,kBAAkB,iBAAiB,oBAAoB,KAAK,IAAI,GAAG;AACzF,YAAM,QAAQ,MAAM,KAAK,oBAAoB,IAAI,OAAO,KAAK;AAC7D,UAAI,OAAO;AACT,iBAAS,QAAQ;AACjB,YAAI,MAAM,QAAQ;AAClB,yBAAiB;AAAA,MACnB;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,gBAAgB,QAAQ,MAAM;AACzC;AAMA,SAAS,yBACP,QACA,YACQ;AACR,WAAS,IAAI,aAAa,GAAG,KAAK,GAAG,KAAK;AACxC,QAAI,OAAO,CAAC,EAAE,SAAS,KAAM,QAAO;AAAA,EACtC;AACA,SAAO;AACT;AASA,eAAe,qBACb,KACA,MACA,OACA,QACA,gBACA,eACe;AACf,QAAM,EAAE,OAAO,kBAAkB,SAAS,IAAI;AAC9C,QAAM,gBAAgB,KAAK,OAAO,cAAc;AAEhD,OAAK,SAAS,UAAU,sBAAsB;AAAA,IAC5C,UAAU,MAAM;AAAA,IAChB;AAAA,EACF,CAAC;AAED,EAAAA,SAAO,KAAK,2BAA2B;AAAA,IACrC,KAAK,MAAM;AAAA,IACX;AAAA,IACA;AAAA,EACF,CAAC;AAED,WAAS,YAAY,GAAG,aAAa,eAAe,aAAa;AAC/D,QAAI,eAAe,GAAG;AACpB,YAAM,IAAI,qBAAqB;AAAA,IACjC;AAEA,IAAAA,SAAO,KAAK,6BAA6B;AAAA,MACvC;AAAA,MACA;AAAA,MACA,KAAK,MAAM;AAAA,IACb,CAAC;AAGD,UAAM,cAAc,KAAK,gBAAgB,MAAM,KAAK,MAAM,EAAE;AAC5D,UAAM,cAAc;AAAA,MAClB;AAAA,MAAU,KAAK;AAAA,MAAU;AAAA,MAAO;AAAA,MAAQ,KAAK;AAAA,MAAQ;AAAA,MAAkB;AAAA,IACzE;AAEA,QAAI;AACJ,QAAI;AACF,qBAAe,MAAM,YAAY,QAAQ,QAAQ;AAAA,IACnD,SAAS,KAAK;AAEZ,MAAAA,SAAO,KAAK,iCAAiC;AAAA,QAC3C;AAAA,QACA,KAAK,MAAM;AAAA,QACX,OAAQ,IAAc;AAAA,MACxB,CAAC;AAED,WAAK,SAAS,UAAU,4BAA4B;AAAA,QAClD,UAAU,MAAM;AAAA,QAChB;AAAA,QACA,QAAQ;AAAA,QACR,UAAU,CAAC,4BAA4B;AAAA,MACzC,CAAC;AAED,UAAI,cAAc,eAAe;AAC/B,cAAM;AAAA,MACR;AAGA,UAAI,iBAAiB,GAAG;AACtB,cAAM,gBAAgB,KAAK,MAAM,OAAO,QAAQ,eAAe;AAAA,UAC7D;AAAA,UACA,gBAAgB,CAAC,iCAAkC,IAAc,OAAO;AAAA,UACxE,WAAW;AAAA,QACb,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAGA,UAAM,SAAS,aAAa;AAC5B,UAAM,SAAS,SAAS,OAAO,SAAS;AAExC,SAAK,SAAS,UAAU,4BAA4B;AAAA,MAClD,UAAU,MAAM;AAAA,MAChB;AAAA,MACA;AAAA,MACA,UAAU,QAAQ;AAAA,IACpB,CAAC;AAED,QAAI,QAAQ;AACV,MAAAA,SAAO,KAAK,0BAA0B;AAAA,QACpC;AAAA,QACA,KAAK,MAAM;AAAA,MACb,CAAC;AACD;AAAA,IACF;AAGA,IAAAA,SAAO,KAAK,+BAA+B;AAAA,MACzC;AAAA,MACA,KAAK,MAAM;AAAA,MACX,UAAU,QAAQ;AAAA,MAClB,eAAe,QAAQ;AAAA,IACzB,CAAC;AAED,QAAI,cAAc,eAAe;AAE/B,WAAK,SAAS,UAAU,wBAAwB;AAAA,QAC9C,UAAU,MAAM;AAAA,QAChB,iBAAiB;AAAA,QACjB,UAAU,QAAQ,kBAAkB,CAAC;AAAA,MACvC,CAAC;AAED,YAAM,UAAU,mCAAmC,aAAa,kCACzC,QAAQ,gBAAgB,KAAK,IAAI,KAAK,SAAS;AACtE,MAAAA,SAAO,KAAK,SAAS,EAAE,KAAK,MAAM,IAAI,CAAC;AAEvC,YAAM,IAAI,iBAAiB,UAAU,SAAS;AAAA,QAC5C,QAAQ,QAAQ,aAAa;AAAA,QAC7B,UAAU;AAAA,MACZ,CAAC;AAAA,IACH;AAGA,QAAI,iBAAiB,GAAG;AACtB,YAAM,gBAAgB,KAAK,MAAM,OAAO,QAAQ,eAAe;AAAA,QAC7D;AAAA,QACA,gBAAgB,QAAQ,kBAAkB,CAAC;AAAA,QAC3C,WAAW,QAAQ,aAAa;AAAA,MAClC,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAMA,eAAe,gBACb,KACA,MACA,OACA,QACA,eACA,YACe;AACf,QAAM,EAAE,OAAO,kBAAkB,SAAS,IAAI;AAE9C,EAAAA,SAAO,KAAK,iCAAiC;AAAA,IAC3C,WAAW,WAAW;AAAA,IACtB,KAAK,MAAM;AAAA,IACX,UAAU,WAAW;AAAA,EACvB,CAAC;AAGD,WAAS,aAAa;AAEtB,MAAI;AACF,UAAM,aAAa,KAAK,gBAAgB,MAAM,KAAK,MAAM,EAAE;AAC3D,UAAM,aAAa;AAAA,MACjB;AAAA,MAAS,KAAK;AAAA,MAAU;AAAA,MAAO;AAAA,MAAQ,KAAK;AAAA,MAAQ;AAAA,MAAkB;AAAA,IACxE;AACA,UAAM,WAAW,QAAQ,QAAQ;AAAA,EACnC,UAAE;AAEA,WAAO,SAAS;AAAA,EAClB;AACF;;;AC/RA,IAAMC,WAAS,OAAW,MAAM,gBAAgB;AAYhD,eAAsB,kBACpB,KACA,MACA,aACe;AACf,QAAM,EAAE,OAAO,YAAY,MAAM,IAAI;AAGrC,OAAK,aAAa,MAAM,KAAK,aAAa,EAAE,+BAA+B,CAAC;AAC5E,QAAM,aAAa,KAAK,gBAAgB,MAAM,GAAG;AACjD,QAAM,WAAW,MAAM,KAAK,sBAAsB,OAAO,YAAY,MAAM,SAAS,UAAU;AAC9F,QAAM,QAAQ,UAAU,OAAO;AAG/B,OAAK,QAAQ,YAAY,MAAM,kCAA2B,QAAQ,EAAE,MAAM,IAAI,MAAS;AACvF,UAAQ,WAAW,8BAA8B,EAAE,UAAU,IAAI,YAAY,KAAK,CAAC;AAGnF,MAAI;AACF,UAAM,KAAK,SAAS,kBAAkB,MAAM,IAAI;AAAA,MAC9C,GAAG,MAAM,OAAO,OAAO,OAAK,CAAC,EAAE,WAAW,cAAc,KAAK,MAAM,aAAa;AAAA,MAChF;AAAA,IACF,CAAC;AAAA,EACH,QAAQ;AAAA,EAER;AAGA,MAAI,qBAAqB,MAAM,KAAK,KAAK,SAAS,KAAK,MAAM,GAAG;AAC9D,SAAK,aAAa,MAAM,KAAK,eAAe,EAAE,wCAAwC,CAAC;AACvF,QAAI;AACF,YAAM,KAAK,oBAAoB,QAAQ;AAAA,QACrC,SAAS,MAAM;AAAA,QACf,UAAU,MAAM;AAAA,QAChB,SAAS,MAAM;AAAA,QACf,OAAO,UAAU;AAAA,MACnB,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,MAAAA,SAAO,KAAK,qCAAqC;AAAA,QAC/C,KAAK,MAAM;AAAA,QACX,OAAQ,IAAc;AAAA,MACxB,CAAC;AAAA,IACH;AAAA,EACF;AAGA,QAAM,YAAY,QACd,EAAE,0BAA0B,EAAE,MAAM,CAAC,IACrC,EAAE,4BAA4B;AAClC,QAAM,iBAAiB,aAAa;AAAA,qBAAiB,UAAU,KAAK;AACpE,MAAI;AACF,UAAM,KAAK,SAAS;AAAA,MAClB,MAAM;AAAA,MACN,EAAE,iCAAiC,EAAE,QAAQ,YAAY,WAAW,eAAe,CAAC;AAAA,IACtF;AAAA,EACF,QAAQ;AAAA,EAER;AAGA,MAAI,KAAK,SAAS;AAChB,UAAM,KAAK,QAAQ,aAAa,MAAM,IAAI,MAAM,KAAK,WAAW;AAAA,EAClE;AAGA,MAAI,YAAY,kBAAkB,KAAK,OAAO,QAAQ,mBAAmB;AACvE,IAAAA,SAAO,KAAK,iDAAiD,EAAE,KAAK,MAAM,IAAI,CAAC;AAAA,EACjF,OAAO;AACL,SAAK,mBAAmB,MAAM,GAAG;AACjC,UAAM,KAAK,aAAa,aAAa,YAAY;AAC/C,UAAI;AACF,cAAM,KAAK,QAAQ,eAAe,MAAM,YAAY,IAAI;AACxD,QAAAA,SAAO,KAAK,uBAAuB,EAAE,KAAK,MAAM,WAAW,CAAC;AAAA,MAC9D,SAAS,KAAK;AACZ,QAAAA,SAAO,KAAK,8BAA8B;AAAA,UACxC,KAAK,MAAM;AAAA,UACX,OAAQ,IAAc;AAAA,QACxB,CAAC;AAAA,MACH;AAAA,IACF,CAAC;AAAA,EACH;AAEA,EAAAA,SAAO,KAAK,8BAA8B,EAAE,KAAK,MAAM,IAAI,CAAC;AAC9D;;;AC9FA,IAAMC,WAAS,OAAW,MAAM,gBAAgB;AAUhD,eAAsB,cACpB,KACA,OACA,OACA,MACe;AACf,QAAM,WAAY,IAAc;AAChC,EAAAA,SAAO,MAAM,2BAA2B,EAAE,KAAK,MAAM,KAAK,OAAO,SAAS,CAAC;AAC3E,UAAQ,WAAW,yBAAyB;AAG5C,QAAM,gBAAgB,KAAK,QAAQ,IAAI,MAAM,GAAG;AAChD,QAAM,gBAAgB,eAAe;AACrC,QAAM,WAAW,6CAAwC,eAAe,aAAa;AAErF,MAAI,2CAAuC,CAAC,UAAU;AACpD,SAAK,QAAQ,WAAW,MAAM,KAAK,SAAS,MAAM,GAAG,GAAG,GAAG,aAAa;AAAA,EAC1E;AAEA,MAAI,UAAU;AACZ,IAAAA,SAAO,KAAK,+DAA+D,EAAE,KAAK,MAAM,IAAI,CAAC;AAC7F,UAAM;AAAA,EACR;AAGA,MAAI;AACF,UAAM,KAAK,SAAS,kBAAkB,MAAM,IAAI;AAAA,MAC9C,GAAG,MAAM,OAAO,OAAO,OAAK,CAAC,EAAE,WAAW,cAAc,KAAK,MAAM,aAAa;AAAA,MAChF;AAAA,MAAe;AAAA,IACjB,CAAC;AAAA,EACH,QAAQ;AAAA,EAER;AAGA,MAAI;AACF,UAAM,KAAK,SAAS;AAAA,MAClB,MAAM;AAAA,MACN,EAAE,8BAA8B,EAAE,OAAO,SAAS,CAAC;AAAA,IACrD;AAAA,EACF,QAAQ;AAAA,EAER;AAGA,MAAI,KAAK,SAAS;AAChB,QAAI;AACF,YAAM,KAAK,QAAQ,aAAa,MAAM,IAAI,MAAM,KAAK,QAAQ;AAAA,IAC/D,SAAS,YAAY;AACnB,MAAAA,SAAO,KAAK,qCAAqC;AAAA,QAC/C,KAAK,MAAM;AAAA,QACX,OAAQ,WAAqB;AAAA,MAC/B,CAAC;AAAA,IACH;AAAA,EACF;AAEA,EAAAA,SAAO,KAAK,oCAAoC,EAAE,KAAK,MAAM,WAAW,CAAC;AACzE,QAAM;AACR;;;AZ5BA,IAAM,gBAAgB,UAAU,QAAQ;AACxC,IAAMC,WAAS,OAAW,MAAM,sBAAsB;AAE/C,IAAM,uBAAN,MAA2B;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAyE;AAAA;AAAA,EAGjF,cAAwB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,YAAY,QAAwB;AAClC,SAAK,WAAW;AAChB,SAAK,mBAAmB,IAAI,iBAAiB,MAAM;AACnD,IAAAA,SAAO,KAAK,kCAAkC;AAAA,EAChD;AAAA,EAEA,YACE,QACA,UACA,KACA,UACA,SACA,iBACA,cACA,kBACA;AACA,SAAK,SAAS;AACd,SAAK,WAAW;AAChB,SAAK,UAAU;AACf,SAAK,WAAW;AAChB,SAAK,UAAU;AACf,SAAK,kBAAkB;AACvB,SAAK,eAAe,gBAAgB,IAAI,WAAW;AACnD,SAAK,WAAW,oBAAoB;AACpC,SAAK,mBAAmB,IAAI,iBAAiB,QAAQ;AAErD,UAAM,OAAO,oBAAoB,OAAO,GAAG,MAAM,OAAO,UAAU,SAAS,SAAS,SAAY,OAAO,UAAU,IAAI;AACrH,SAAK,cAAc,eAAe,IAAI;AACtC,SAAK,mBAAmB,uBAAuB,KAAK,WAAW;AAC/D,IAAAA,SAAO,KAAK,0BAA0B,EAAE,MAAM,KAAK,YAAY,MAAM,QAAQ,OAAO,GAAG,KAAK,CAAC;AAE7F,SAAK,gBAAgB,IAAI,cAAc;AAAA,MACrC,iBAAiB,OAAO,IAAI;AAAA,MAC5B,kBAAkB,OAAO,IAAI;AAAA,IAC/B,CAAC;AACD,SAAK,mBAAmB,IAAI,iBAAiB;AAC7C,SAAK,sBAAsB,IAAI,oBAAoB,QAAQ;AAE3D,SAAK,uBAAuB;AAAA,EAC9B;AAAA,EAEA,mBAAkC;AAAE,WAAO,KAAK;AAAA,EAAe;AAAA,EAC/D,sBAAwC;AAAE,WAAO,KAAK;AAAA,EAAkB;AAAA,EACxE,kBAA8B;AAAE,WAAO,KAAK;AAAA,EAAc;AAAA;AAAA,EAG1D,WAAW,SAA8E;AACvF,SAAK,UAAU;AAAA,EACjB;AAAA,EAEA,MAAM,oBAAmC;AACvC,IAAAA,SAAO,KAAK,qCAAqC;AACjD,QAAI,UAAU;AAEd,QAAI;AACF,YAAM,YAAY,MAAM,KAAK,QAAQ,aAAa;AAClD,iBAAW,SAAS,WAAW;AAE7B,YAAI,UAAU,KAAK,OAAO,QAAQ,WAAY;AAC9C,YAAI,CAAC,MAAM,SAAS,SAAS,EAAG;AAEhC,YAAI;AAEF,gBAAM,UAAUC,MAAK,KAAK,OAAO,MAAM;AACvC,cAAI;AACF,kBAAMC,IAAG,OAAO,OAAO;AAAA,UACzB,QAAQ;AACN,YAAAF,SAAO,KAAK,qDAAqD,EAAE,KAAK,MAAM,CAAC;AAC/E,kBAAM,KAAK,QAAQ,eAAe,OAAO,IAAI,EAAE,MAAM,MAAM;AAAA,YAAC,CAAC;AAC7D,kBAAM,KAAK,QAAQ,cAAc;AACjC;AACA;AAAA,UACF;AAEA,gBAAM,QAAQ,IAAI,cAAc,KAAK;AAGrC,cAAI,MAAM,MAAM,mBAAmB,GAAG;AACpC,YAAAA,SAAO,KAAK,wCAAwC,EAAE,KAAK,MAAM,CAAC;AAClE,kBAAM,MAAM,YAAY;AACxB;AAAA,UACF;AAGA,gBAAM,YAAYC,MAAK,KAAK,OAAO,QAAQ,YAAY;AACvD,cAAI;AACF,kBAAMC,IAAG,OAAO,SAAS;AACzB,YAAAF,SAAO,KAAK,4BAA4B,EAAE,MAAM,UAAU,CAAC;AAC3D;AAAA,UACF,QAAQ;AAAA,UAER;AAAA,QACF,SAAS,KAAK;AACZ,UAAAA,SAAO,KAAK,kCAAkC,EAAE,KAAK,OAAO,OAAQ,IAAc,QAAQ,CAAC;AAAA,QAC7F;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,MAAAA,SAAO,KAAK,wCAAwC,EAAE,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACvF;AAGA,UAAM,gBAAgBC,MAAK,KAAK,KAAK,OAAO,QAAQ,YAAY,QAAQ,YAAY;AACpF,QAAI;AACF,YAAMC,IAAG,OAAO,aAAa;AAC7B,MAAAF,SAAO,KAAK,sCAAsC,EAAE,MAAM,cAAc,CAAC;AACzE;AAAA,IACF,QAAQ;AAAA,IAER;AAEA,IAAAA,SAAO,KAAK,gCAAgC,EAAE,QAAQ,CAAC;AAAA,EACzD;AAAA,EAEQ,yBAA+B;AACrC,eAAW,UAAU,KAAK,QAAQ,OAAO,GAAG;AAC1C,UAAI,OAAO,OAAO;AAChB,aAAK,cAAc,QAAQ,OAAO,MAAM,GAAG,OAAO,KAAK;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AAAA,EAEA,iBAA8B;AAC5B,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,aAAa,UAAkB,MAAc,SAAuB;AAC1E,SAAK,SAAS,UAAU,qBAAqB,EAAE,UAAU,MAAM,QAAQ,CAAC;AAAA,EAC1E;AAAA,EAEQ,uBAAuB,UAAkB,YAAqC;AACpF,UAAM,aAAaC,MAAK,KAAK,KAAK,OAAO,QAAQ,iBAAiB,SAAS,QAAQ,EAAE;AACrF,UAAM,UAAUA,MAAK,KAAK,YAAY,KAAK,OAAO,QAAQ,aAAa;AACvE,WAAO,EAAE,YAAY,SAAS,YAAY,SAAS;AAAA,EACrD;AAAA,EAEA,MAAc,eAAe,OAAuC;AAClE,UAAM,YAAY,MAAM,KAAK,QAAQ,aAAa;AAClD,QAAI,UAAU,SAAS,MAAM,UAAU,GAAG;AAExC,YAAM,UAAUA,MAAK,KAAK,MAAM,YAAY,MAAM;AAClD,UAAI;AACF,cAAMC,IAAG,OAAO,OAAO;AACvB,QAAAF,SAAO,KAAK,6BAA6B,EAAE,KAAK,MAAM,WAAW,CAAC;AAClE;AAAA,MACF,QAAQ;AACN,QAAAA,SAAO,KAAK,oDAAoD,EAAE,KAAK,MAAM,WAAW,CAAC;AACzF,cAAM,KAAK,QAAQ,eAAe,MAAM,YAAY,IAAI;AACxD,cAAM,KAAK,QAAQ,cAAc;AAAA,MACnC;AAAA,IACF;AAEA,UAAM,KAAK,sBAAsB,MAAM,UAAU;AAEjD,UAAM,cAAc,MAAM,KAAK,QAAQ,aAAa,MAAM,UAAU;AACpE,QAAI,aAAa;AACf,YAAM,KAAK,QAAQ,oBAAoB,MAAM,YAAY,MAAM,UAAU;AACzE;AAAA,IACF;AAEA,UAAM,eAAe,MAAM,KAAK,QAAQ,mBAAmB,MAAM,UAAU;AAC3E,QAAI,cAAc;AAChB,YAAM,KAAK,QAAQ,oBAAoB,MAAM,YAAY,MAAM,UAAU;AACzE;AAAA,IACF;AAEA,UAAM,KAAK,QAAQ;AAAA,MACjB,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU,KAAK,OAAO,QAAQ,UAAU;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,MAAc,sBAAsB,KAA4B;AAC9D,QAAI;AACF,YAAME,IAAG,OAAO,GAAG;AAAA,IACrB,QAAQ;AACN;AAAA,IACF;AACA,IAAAF,SAAO,KAAK,wDAAwD,EAAE,IAAI,CAAC;AAC3E,UAAME,IAAG,GAAG,KAAK,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACjD,UAAM,KAAK,QAAQ,cAAc;AAAA,EACnC;AAAA,EAEA,MAAc,gBAAgB,OAAuC;AACnE,QAAI;AACF,YAAM,KAAK,QAAQ,eAAe,MAAM,YAAY,IAAI;AACxD,MAAAF,SAAO,KAAK,uBAAuB,EAAE,KAAK,MAAM,WAAW,CAAC;AAAA,IAC9D,SAAS,KAAK;AACZ,MAAAA,SAAO,KAAK,8BAA8B,EAAE,KAAK,MAAM,YAAY,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACpG;AAAA,EACF;AAAA,EAEA,MAAc,oBAAoB,SAAgC;AAChE,IAAAA,SAAO,KAAK,uCAAuC,EAAE,QAAQ,CAAC;AAE9D,UAAM,YAAY,oBAAoB,KAAK;AAC3C,UAAM,SAAS,UAAU,UAAU,eAAe,YAAY;AAC9D,UAAM,gBAAgB,CAAC,OAAO,QAAQ,QAAQ,KAAK,EAAE,KAAK,OAAK,OAAO,SAAS,CAAC,CAAC;AAEjF,QAAI,eAAe;AACjB,YAAM,QAAQ,MAAM,KAAK,kBAAkB,OAAO;AAClD,UAAI,OAAO;AACT,QAAAA,SAAO,KAAK,4CAAuC;AACnD;AAAA,MACF;AAAA,IACF;AAEA,UAAM,aAAa,UAAU,UAAU;AACvC,UAAM,cAAc,UAAU,UAAU;AACxC,UAAM,CAAC,KAAK,GAAG,IAAI,IAAI,WAAW,MAAM,KAAK;AAE7C,QAAI;AACF,YAAM,cAAc,KAAK,MAAM;AAAA,QAC7B,KAAK;AAAA,QACL,WAAW,KAAK,OAAO;AAAA,QACvB,SAAS;AAAA,MACX,CAAC;AACD,MAAAA,SAAO,KAAK,wBAAwB;AAAA,IACtC,SAAS,KAAK;AACZ,UAAI,aAAa;AACf,QAAAA,SAAO,KAAK,GAAG,UAAU,2CAA2C;AAAA,UAClE,OAAQ,IAAc;AAAA,QACxB,CAAC;AACD,cAAM,CAAC,aAAa,GAAG,YAAY,IAAI,YAAY,MAAM,KAAK;AAC9D,YAAI;AACF,gBAAM,cAAc,aAAa,cAAc;AAAA,YAC7C,KAAK;AAAA,YACL,WAAW,KAAK,OAAO;AAAA,YACvB,SAAS;AAAA,UACX,CAAC;AACD,UAAAA,SAAO,KAAK,mCAAmC;AAAA,QACjD,SAAS,UAAU;AACjB,UAAAA,SAAO,KAAK,gCAAgC;AAAA,YAC1C,OAAQ,SAAmB;AAAA,UAC7B,CAAC;AAAA,QACH;AAAA,MACF,OAAO;AACL,QAAAA,SAAO,KAAK,0CAA0C;AAAA,UACpD,OAAQ,IAAc;AAAA,QACxB,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,kBAAkB,SAAmC;AACjE,UAAM,YAAYC,MAAK,KAAK,SAAS,gBAAgB,MAAM;AAC3D,QAAI;AACF,YAAMC,IAAG,OAAO,SAAS;AACzB,MAAAF,SAAO,KAAK,2CAA2C;AACvD,aAAO;AAAA,IACT,QAAQ;AAAA,IAER;AAEA,UAAM,WAAWC,MAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,cAAc;AACtE,UAAM,WAAWA,MAAK,KAAK,SAAS,cAAc;AAClD,QAAI;AACF,YAAMC,IAAG,OAAO,QAAQ;AAAA,IAC1B,QAAQ;AACN,MAAAF,SAAO,KAAK,mDAAmD,EAAE,SAAS,CAAC;AAC3E,aAAO;AAAA,IACT;AAEA,IAAAA,SAAO,KAAK,wDAAwD,EAAE,UAAU,SAAS,CAAC;AAC1F,QAAI;AACF,YAAM,cAAc,MAAM,CAAC,OAAO,QAAQ,GAAG,EAAE,SAAS,IAAO,CAAC;AAEhE,YAAM,cAAc,MAAM,CAAC,MAAM,kBAAkB,UAAU,QAAQ,GAAG;AAAA,QACtE,SAAS;AAAA,MACX,CAAC;AACD,MAAAA,SAAO,KAAK,oCAAoC;AAChD,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,MAAAA,SAAO,KAAK,8CAA8C;AAAA,QACxD,OAAQ,IAAc;AAAA,MACxB,CAAC;AACD,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,aAAa,UAAiC;AAClD,UAAM,SAAS,KAAK,QAAQ,IAAI,QAAQ;AACxC,QAAI,CAAC,OAAQ,OAAM,IAAI,mBAAmB,QAAQ;AAElD,UAAM,QAAQ,KAAK,uBAAuB,UAAU,OAAO,UAAU;AACrE,IAAAA,SAAO,KAAK,4CAAuC,EAAE,UAAU,YAAY,OAAO,WAAW,CAAC;AAE9F,SAAK,SAAS,cAAc,MAAM,OAAO;AAEzC,SAAK,mBAAmB,QAAQ;AAEhC,QAAI;AACF,YAAM,UAAU,MAAM,KAAK,SAAS,kBAAkB,cAAc,MAAM,CAAC;AAC3E,MAAAA,SAAO,KAAK,0BAA0B,EAAE,UAAU,QAAQ,CAAC;AAAA,IAC7D,SAAS,KAAK;AACZ,MAAAA,SAAO,KAAK,iCAAiC,EAAE,UAAU,OAAQ,IAAc,QAAQ,CAAC;AAAA,IAC1F;AAEA,UAAM,KAAK,aAAa,aAAa,YAAY;AAC/C,YAAM,KAAK,gBAAgB,KAAK;AAChC,UAAI;AAAE,cAAM,KAAK,QAAQ,aAAa,OAAO,UAAU;AAAA,MAAG,QAAQ;AAAA,MAA6B;AAC/F,UAAI;AAAE,cAAM,KAAK,QAAQ,mBAAmB,OAAO,UAAU;AAAA,MAAG,QAAQ;AAAA,MAAoC;AAAA,IAC9G,CAAC;AAED,SAAK,QAAQ,UAAU,QAAQ;AAC/B,IAAAA,SAAO,KAAK,mBAAmB,EAAE,SAAS,CAAC;AAAA,EAC7C;AAAA,EAEA,MAAM,YAAY,UAAiC;AACjD,UAAM,SAAS,KAAK,QAAQ,IAAI,QAAQ;AACxC,QAAI,CAAC,OAAQ,OAAM,IAAI,mBAAmB,QAAQ;AAElD,UAAM,QAAQ,KAAK,uBAAuB,UAAU,OAAO,UAAU;AACrE,IAAAA,SAAO,KAAK,kDAA6C,EAAE,UAAU,YAAY,OAAO,WAAW,CAAC;AAGpG,SAAK,SAAS,cAAc,MAAM,OAAO;AAGzC,SAAK,mBAAmB,QAAQ;AAGhC,QAAI;AACF,YAAM,KAAK,SAAS,uBAAuB,cAAc,MAAM,GAAG,aAAa;AAAA,IACjF,SAAS,KAAK;AACZ,MAAAA,SAAO,KAAK,qCAAqC,EAAE,UAAU,OAAQ,IAAc,QAAQ,CAAC;AAAA,IAC9F;AAGA,UAAM,KAAK,aAAa,aAAa,YAAY;AAC/C,YAAM,KAAK,gBAAgB,KAAK;AAChC,UAAI;AAAE,cAAM,KAAK,QAAQ,aAAa,OAAO,UAAU;AAAA,MAAG,QAAQ;AAAA,MAA6B;AAC/F,UAAI;AAAE,cAAM,KAAK,QAAQ,mBAAmB,OAAO,UAAU;AAAA,MAAG,QAAQ;AAAA,MAAoC;AAAA,IAC9G,CAAC;AAGD,SAAK,QAAQ,OAAO,QAAQ;AAC5B,IAAAA,SAAO,KAAK,mBAAmB,EAAE,SAAS,CAAC;AAAA,EAC7C;AAAA,EAEA,eAAe,UAAkB,OAAqB;AACpD,UAAM,SAAS,KAAK,QAAQ,IAAI,QAAQ;AACxC,QAAI,CAAC,OAAQ,OAAM,IAAI,mBAAmB,QAAQ;AAElD,UAAM,WAAW,KAAK,4BAA4B,MAAM;AACxD,UAAM,UAAU,uBAAuB,QAAQ;AAC/C,QAAI,CAAC,QAAQ,YAAY,KAAK,GAAG;AAC/B,YAAM,IAAI,kBAAkB,KAAK;AAAA,IACnC;AAEA,IAAAA,SAAO,KAAK,6BAA6B,EAAE,UAAU,MAAM,CAAC;AAC5D,SAAK,QAAQ,aAAa,UAAU,OAAO,QAAQ;AAAA,EACrD;AAAA,EAEQ,4BAA4B,QAAuC;AACzE,QAAI,OAAO,cAAc;AACvB,aAAO,eAAe,OAAO,YAAY;AAAA,IAC3C;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,aAAa,OAAqC;AACtD,WAAO,oBAAoB,MAAM,KAAK,MAAM,KAAK,kBAAkB,KAAK,CAAC;AAAA,EAC3E;AAAA,EAEQ,YAA8B;AACpC,WAAO;AAAA,MACL,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,SAAS,KAAK;AAAA,MACd,cAAc,KAAK;AAAA,MACnB,UAAU,KAAK;AAAA,MACf,SAAS,KAAK;AAAA,MACd,iBAAiB,KAAK;AAAA,MACtB,qBAAqB,KAAK;AAAA,MAC1B,eAAe,KAAK;AAAA,MACpB,kBAAkB,KAAK;AAAA,MACvB,UAAU,KAAK;AAAA,MACf,SAAS,KAAK;AAAA,MACd,cAAc,CAAC,KAAK,MAAM,QAAQ,KAAK,aAAa,KAAK,MAAM,GAAG;AAAA,MAClE,gBAAgB,CAAC,UAAU,KAAK,eAAe,KAAK;AAAA,MACpD,qBAAqB,CAAC,YAAY,KAAK,oBAAoB,OAAO;AAAA,MAClE,iBAAiB,CAAC,KAAK,YAAY,KAAK,gBAAgB,KAAK,OAAO;AAAA,MACpE,mBAAmB,CAAC,WAAW,KAAK,kBAAkB,MAAM;AAAA,MAC5D,qBAAqB,CAAC,QAAQ,KAAK,oBAAoB,GAAG;AAAA,MAC1D,qBAAqB,CAAC,OAAO,UAAU,KAAK,oBAAoB,OAAO,KAAK;AAAA,MAC5E,oBAAoB,CAAC,QAAQ,KAAK,mBAAmB,GAAG;AAAA,MACxD,uBAAuB,CAAC,OAAO,QAAQ,SAAS,eAC9C,KAAK,sBAAsB,OAAO,QAAQ,SAAS,UAAU;AAAA,MAC/D,iBAAiB,CAAC,QAAQ,KAAK,gBAAgB,GAAG;AAAA,IACpD;AAAA,EACF;AAAA,EAEA,MAAc,kBAAkB,OAAqC;AACnE,UAAM,aAAa,GAAG,KAAK,OAAO,QAAQ,YAAY,IAAI,MAAM,GAAG;AACnE,UAAM,QAAQ,KAAK,uBAAuB,MAAM,KAAK,UAAU;AAE/D,IAAAA,SAAO,KAAK,oBAAoB,EAAE,KAAK,MAAM,KAAK,OAAO,MAAM,OAAO,YAAY,UAAU,MAAM,WAAW,CAAC;AAC9G,YAAQ,WAAW,oBAAoB,EAAE,UAAU,KAAK,YAAY,KAAK,CAAC;AAE1E,UAAM,aAAa,KAAK,iBAAiB,IAAI,MAAM,GAAG;AACtD,UAAM,SAAS,0BAA0B,OAAO,UAAU;AAE1D,QAAI,SAAS,KAAK,QAAQ,IAAI,MAAM,GAAG;AACvC,UAAM,UAAU,QAAQ;AACxB,QAAI,SAAS;AACX,cAAQ,WAAW,0BAA0B;AAAA,IAC/C;AAEA,QAAI,CAAC,QAAQ;AACX,eAAS,KAAK,QAAQ,OAAO;AAAA,QAC3B;AAAA,QACA;AAAA,QACA,cAAc,KAAK,YAAY;AAAA,QAC/B,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAEA,QAAI,CAAC,OAAO,cAAc;AACxB,WAAK,QAAQ,YAAY,MAAM,KAAK,OAAO,OAAO,EAAE,cAAc,KAAK,YAAY,KAAK,CAAQ;AAChG,aAAO,eAAe,KAAK,YAAY;AAAA,IACzC;AAEA,UAAM,mBAAmB,KAAK,4BAA4B,MAAM;AAChE,UAAM,UAAU,uBAAuB,gBAAgB;AACvD,UAAM,WAAyB,EAAE,QAAQ,YAAY,cAAc,iBAAiB,KAAK;AAEzF,UAAM,MAA8B;AAAA,MAClC;AAAA,MAAO;AAAA,MAAY;AAAA,MAAO;AAAA,MAAQ;AAAA,MAClC,aAAa;AAAA,MACb,kBAAkB;AAAA,MAClB;AAAA,MAAQ;AAAA,IACV;AAEA,UAAM,OAAO,KAAK,UAAU;AAE5B,QAAI;AACF,YAAM,EAAE,OAAO,OAAO,IAAI,MAAM,aAAa,KAAK,IAAI;AACtD,YAAM,cAAc,MAAM,iBAAiB,KAAK,MAAM,OAAO,MAAM;AACnE,UAAI,YAAY,OAAQ;AACxB,YAAM,kBAAkB,KAAK,MAAM,WAAW;AAAA,IAChD,SAAS,KAAK;AACZ,YAAM,cAAc,KAAK,OAAO,OAAO,IAAI;AAAA,IAC7C;AAAA,EACF;AAAA,EAEA,MAAc,sBACZ,OACA,YACA,SACA,YACoC;AACpC,QAAI;AACF,YAAM,aAAa,KAAK,iBAAiB,IAAI,MAAM,GAAG;AACtD,YAAM,SAAS,YAAY,QAAQ,KAAK,KACnC,cAAc,MAAM,eAAe,EAAE;AAE1C,YAAM,QAAQ,gBAAgB,MAAM,KAAK,MAAM,OAAO,MAAM;AAC5D,UAAI,cAAc,sBAAsB;AAAA,QACtC,UAAU,MAAM;AAAA,QAChB,YAAY,MAAM;AAAA,QAClB,kBAAkB,MAAM,eAAe;AAAA,QACvC;AAAA,QACA,SAAS;AAAA,MACX,CAAC;AAED,UAAI,YAAY;AACd,uBAAe;AAAA;AAAA;AAAA;AAAA,YAAoC,UAAU;AAAA,MAC/D;AAEA,YAAM,KAAK,MAAM,KAAK,SAAS,mBAAmB;AAAA,QAChD,cAAc;AAAA,QACd,cAAc,KAAK,OAAO,QAAQ;AAAA,QAClC;AAAA,QACA;AAAA,MACF,CAAC;AAED,MAAAA,SAAO,KAAK,sCAAsC;AAAA,QAChD,KAAK,MAAM;AAAA,QAAK,OAAO,GAAG;AAAA,QAAK,OAAO,GAAG;AAAA,MAC3C,CAAC;AACD,aAAO,EAAE,KAAK,GAAG,SAAS,KAAK,GAAG,IAAI;AAAA,IACxC,SAAS,KAAK;AACZ,YAAM,WAAY,IAAc;AAChC,MAAAA,SAAO,KAAK,+DAA+D;AAAA,QACzE,KAAK,MAAM;AAAA,QAAK,OAAO;AAAA,MACzB,CAAC;AAED,UAAI,SAAS,SAAS,gBAAgB,GAAG;AACvC,eAAO,KAAK,4BAA4B,MAAM,KAAK,UAAU;AAAA,MAC/D;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,4BACZ,UACA,YACoC;AACpC,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,SAAS;AAAA,QACnC;AAAA,QACA,KAAK,OAAO,QAAQ;AAAA,MACtB;AACA,UAAI,UAAU;AACZ,QAAAA,SAAO,KAAK,gCAAgC;AAAA,UAC1C,KAAK;AAAA,UAAU,OAAO,SAAS;AAAA,UAAK,OAAO,SAAS;AAAA,QACtD,CAAC;AACD,eAAO,EAAE,KAAK,SAAS,SAAS,KAAK,SAAS,IAAI;AAAA,MACpD;AAAA,IACF,SAAS,SAAS;AAChB,MAAAA,SAAO,KAAK,yCAAyC;AAAA,QACnD,KAAK;AAAA,QAAU,OAAQ,QAAkB;AAAA,MAC3C,CAAC;AAAA,IACH;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,oBAAoB,UAA2B;AACrD,WAAO,qBAAqB,UAAU,KAAK,SAAS,KAAK,MAAM,KAC1D,KAAK,OAAO,QAAQ;AAAA,EAC3B;AAAA,EAEQ,kBAAkB,aAAgC;AACxD,UAAM,aAAa,KAAK,OAAO,OAAO;AACtC,QAAI,CAAC,WAAW,OAAQ,QAAO;AAC/B,WAAO,YAAY,KAAK,OAAK,WAAW,SAAS,CAAC,CAAC;AAAA,EACrD;AAAA,EAEQ,gBAAgB,KAAa,SAAsC;AACzE,WAAO;AAAA,MACL,cAAc,OAAO,UAAU;AAC7B,aAAK,QAAQ,YAAY,yCAA8B,EAAE,cAAc,MAAM,CAAC;AAAA,MAChF;AAAA,MACA,aAAa,OAAO,UAAU;AAC5B,aAAK,QAAQ,YAAY,mCAA2B,EAAE,cAAc,MAAM,CAAC;AAAA,MAC7E;AAAA,MACA,eAAe,OAAO,QAAQ,UAAU;AACtC,aAAK,QAAQ,WAAW,KAAK,yCAA8B;AAAA,MAC7D;AAAA,MACA,WAAW,OAAO,QAAQ;AACxB,YAAI;AAAE,gBAAM,KAAK,SAAS,gBAAgB,SAAS,GAAG;AAAA,QAAG,QAAQ;AAAA,QAAe;AAAA,MAClF;AAAA,MACA,mBAAmB,MAAM,0BAA0B,KAAK,KAAK,SAAS,KAAK,MAAM;AAAA,MACjF,cAAc,MAAM,qBAAqB,KAAK,KAAK,SAAS,KAAK,MAAM;AAAA,IACzE;AAAA,EACF;AAAA,EAEA,MAAc,oBACZ,OACA,OAC0B;AAC1B,QAAI;AACF,WAAK,aAAa,MAAM,KAAK,UAAU,EAAE,6BAA6B,CAAC;AACvE,YAAM,QAAQ,MAAM,KAAK,cAAc,SAAS,MAAM,GAAG;AACzD,YAAM,QAAQ;AAEd,WAAK,QAAQ,YAAY,MAAM,KAAK,KAAK,QAAQ,IAAI,MAAM,GAAG,EAAG,OAAO;AAAA,QACtE;AAAA,QACA,mBAAkB,oBAAI,KAAK,GAAE,YAAY;AAAA,MAC3C,CAAQ;AAER,YAAM,KAAK,iBAAiB,aAAa,OAAO,KAAK;AAErD,YAAM,aAAa,KAAK,gBAAgB,MAAM,GAAG;AACjD,UAAI,YAAY;AACd,YAAI;AACF,gBAAM,KAAK,SAAS;AAAA,YAClB,MAAM;AAAA,YACN,KAAK,oBAAoB,OAAO,UAAU;AAAA,UAC5C;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAEA,WAAK,aAAa,MAAM,KAAK,eAAe,EAAE,mCAAmC,EAAE,KAAK,cAAc,MAAM,CAAC,CAAC;AAC9G,WAAK,SAAS,UAAU,qBAAqB;AAAA,QAC3C,UAAU,MAAM;AAAA,QAChB,MAAM;AAAA,QACN,SAAS,cAAc;AAAA,MACzB,CAAC;AAED,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,MAAAA,SAAO,MAAM,mCAAmC;AAAA,QAC9C,KAAK,MAAM;AAAA,QACX,OAAQ,IAAc;AAAA,MACxB,CAAC;AACD,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,mBAAmB,UAAwB;AACzC,SAAK,iBAAiB,YAAY,QAAQ;AAC1C,SAAK,cAAc,QAAQ,QAAQ;AACnC,UAAM,SAAS,KAAK,QAAQ,IAAI,QAAQ;AACxC,QAAI,QAAQ,OAAO;AACjB,WAAK,QAAQ,YAAY,UAAU,OAAO,OAAO;AAAA,QAC/C,OAAO;AAAA,QACP,kBAAkB;AAAA,MACpB,CAAQ;AAAA,IACV;AAAA,EACF;AAAA,EAEA,iBAAyB;AACvB,QAAI,KAAK,OAAO,QAAQ,KAAM,QAAO,KAAK,OAAO,QAAQ;AACzD,WAAO,WAAW;AAAA,EACpB;AAAA,EAEA,gBAAgB,UAAiC;AAC/C,UAAM,QAAQ,KAAK,cAAc,iBAAiB,QAAQ;AAC1D,QAAI,CAAC,MAAO,QAAO;AACnB,UAAM,OAAO,KAAK,eAAe;AACjC,WAAO,WAAW,IAAI,IAAI,MAAM,YAAY;AAAA,EAC9C;AAAA,EAEQ,oBAAoB,OAAiB,YAA4B;AACvE,UAAM,OAAO,KAAK,eAAe;AACjC,UAAM,WAAW,KAAK,MAAM,KAAK,OAAO,QAAQ,SAAS,KAAK,KAAK,IAAK;AACxE,WAAO;AAAA,MACL,EAAE,mCAAmC;AAAA,MACrC;AAAA,MACA,EAAE,yCAAyC;AAAA,MAC3C,EAAE,sCAAsC;AAAA,MACxC,KAAK,EAAE,sCAAsC,CAAC,MAAM,UAAU;AAAA,MAC9D,KAAK,EAAE,wCAAwC,CAAC,aAAa,IAAI,IAAI,MAAM,WAAW;AAAA,MACtF;AAAA,MACA,EAAE,kCAAkC;AAAA,MACpC,EAAE,sCAAsC,EAAE,OAAO,SAAS,CAAC;AAAA,IAC7D,EAAE,KAAK,IAAI;AAAA,EACb;AAAA,EAEA,MAAM,gBAAgB,UAAiC;AACrD,UAAM,SAAS,KAAK,QAAQ,IAAI,QAAQ;AACxC,QAAI,CAAC,OAAQ,OAAM,IAAI,mBAAmB,QAAQ;AAElD,UAAM,aAAa,KAAK,OAAO,QAAQ;AACvC,UAAM,aAAa,OAAO;AAE1B,IAAAA,SAAO,KAAK,gCAAgC,EAAE,UAAU,YAAY,WAAW,CAAC;AAGhF,SAAK,QAAQ,YAAY,sDAAsC;AAC/D,SAAK,SAAS,UAAU,oBAAoB,EAAE,SAAS,CAAC;AAGxD,QAAI;AACF,YAAM,KAAK,SAAS;AAAA,QAClB,cAAc,MAAM;AAAA,QACpB,EAAE,yBAAyB,EAAE,QAAQ,YAAY,WAAW,CAAC;AAAA,MAC/D;AAAA,IACF,QAAQ;AAAA,IAAe;AAEvB,UAAM,QAAQ,KAAK,uBAAuB,UAAU,UAAU;AAE9D,QAAI;AAEF,YAAM,KAAK,aAAa,aAAa,YAAY;AAC/C,cAAM,KAAK,QAAQ,MAAM;AACzB,cAAM,KAAK,eAAe,KAAK;AAAA,MACjC,CAAC;AAED,YAAM,QAAQ,IAAI,cAAc,MAAM,UAAU;AAGhD,YAAM,MAAM,SAAS,UAAU;AAG/B,YAAM,KAAK,iBAAiB,QAAQ;AAAA,QAClC;AAAA,QACA,WAAW,UAAU,UAAU;AAAA,QAC/B,SAAS,MAAM;AAAA,QACf;AAAA,QACA,WAAW;AAAA,QACX,gBAAgB,KAAK,OAAO,GAAG;AAAA,QAC/B,SAAS,CAAC,UAAU;AAClB,eAAK,SAAS,UAAU,gBAAgB;AAAA,YACtC;AAAA,YACA,OAAO;AAAA,YACP;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF,CAAC;AAKD,MAAAA,SAAO,KAAK,kDAAkD,EAAE,SAAS,CAAC;AAC1E,YAAM,SAAS,IAAI,gBAAgB,MAAM,SAAS,QAAQ;AAC1D,aAAO,UAAU;AAEjB,YAAM,aAAa,uBAAuB,KAAK,4BAA4B,MAAM,CAAC;AAClF,YAAM,gBAAgB,KAAK,gBAAgB,UAAU,cAAc,MAAM,CAAC;AAC1E,YAAM,cAAc,YAAY,UAAU,KAAK,UAAU,OAAO,QAAQ,KAAK,QAAQ,YAAY,aAAa;AAE9G,YAAM,YAA0B;AAAA,QAC9B,QAAQ;AAAA,UACN,UAAU,MAAM,QAAQ;AAAA,UACxB,WAAW;AAAA,YACT,QAAQ;AAAA,YACR,YAAY,OAAO,cAAc,MAAM,CAAC;AAAA,YACxC,WAAW,OAAO,QAAQ;AAAA,UAC5B;AAAA,UACA,OAAO,SAAS,MAAM;AAAA,UACtB,aAAa;AAAA,UACb,WAAW,OAAO;AAAA,QACpB;AAAA,QACA;AAAA,QACA,cAAc,OAAO;AAAA,MACvB;AAEA,YAAM,YAAY,QAAQ,SAAS;AAGnC,YAAM,MAAM,UAAU,UAAU;AAGhC,WAAK,QAAQ,YAAY,qCAA8B;AACvD,WAAK,SAAS,UAAU,qBAAqB,EAAE,SAAS,CAAC;AAGzD,UAAI;AACF,cAAM,KAAK,SAAS;AAAA,UAClB,cAAc,MAAM;AAAA,UACpB,EAAE,4BAA4B,EAAE,QAAQ,YAAY,WAAW,CAAC;AAAA,QAClE;AAAA,MACF,QAAQ;AAAA,MAAe;AAEvB,YAAM,KAAK,YAAY,OAAO,OAAO,EAAE,4BAA4B,CAAC;AAEpE,MAAAA,SAAO,KAAK,iCAAiC,EAAE,SAAS,CAAC;AAAA,IAC3D,SAAS,KAAK;AACZ,YAAM,WAAY,IAAc;AAChC,MAAAA,SAAO,MAAM,8BAA8B,EAAE,UAAU,OAAO,SAAS,CAAC;AAGxE,UAAI;AACF,cAAM,QAAQ,IAAI,cAAc,MAAM,UAAU;AAChD,YAAI,MAAM,MAAM,mBAAmB,GAAG;AACpC,gBAAM,MAAM,YAAY;AAAA,QAC1B;AAAA,MACF,QAAQ;AAAA,MAA6B;AAErC,WAAK,QAAQ,WAAW,UAAU,SAAS,MAAM,GAAG,GAAG,+CAA+B;AACtF,WAAK,SAAS,UAAU,mBAAmB,EAAE,UAAU,OAAO,SAAS,CAAC;AAExE,UAAI;AACF,cAAM,KAAK,SAAS;AAAA,UAClB,cAAc,MAAM;AAAA,UACpB,EAAE,0BAA0B,EAAE,OAAO,SAAS,CAAC;AAAA,QACjD;AAAA,MACF,QAAQ;AAAA,MAAe;AAAA,IACzB;AAAA,EACF;AAAA,EAEQ,oBAAoB,OAA8B;AACxD,UAAM,QAAQ,MAAM,MAAM,uBAAuB;AACjD,WAAO,QAAQ,SAAS,MAAM,CAAC,GAAG,EAAE,IAAI;AAAA,EAC1C;AAAA,EAEA,MAAc,YAAY,OAA2B,MAA6B;AAChF,QAAI,CAAC,MAAO;AACZ,UAAM,QAAQ,KAAK,oBAAoB,KAAK;AAC5C,QAAI,CAAC,MAAO;AACZ,QAAI;AACF,YAAM,KAAK,SAAS,uBAAuB,OAAO,IAAI;AAAA,IACxD,SAAS,KAAK;AACZ,MAAAA,SAAO,KAAK,2BAA2B,EAAE,OAAO,OAAQ,IAAc,QAAQ,CAAC;AAAA,IACjF;AAAA,EACF;AACF;;;Aa50BA,SAAS,kBAAkB;;;ACApB,SAAS,oBAAoB,YAA4B;AAC9D,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBP,UAAU;AAAA;AAAA;AAAA;AAIZ;AAEO,SAAS,kBAAkB,KAAa,OAAuB;AACpE,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,qBAQH,KAAK,sBAAO,QAAQ,IAAI,6NAAyC,EAAE;AAAA;AAAA;AAAA;AAAA,EAIvE,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAUL;AAEO,SAAS,kBAAkB,WAA2B;AAC3D,SAAO;AAAA;AAAA,EAEP,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQX;;;ADvDA,IAAMG,WAAS,OAAW,MAAM,YAAY;AAkC5C,SAAS,sBACP,UACA,WACU;AACV,SAAO;AAAA,IACL,MAAM,SAAS;AAAA,IACf,QAAQ,SAAS;AAAA,IACjB,gBAAgB;AAAA,IAChB,gBAAgB,SAAS;AAAA,IACzB,OAAO,SAAS;AAAA,EAClB;AACF;AAEO,IAAM,oBAAN,MAAwB;AAAA,EACrB,WAAW,oBAAI,IAA+B;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,QAAgB;AAC1B,SAAK,SAAS,OAAO;AACrB,SAAK,UAAU,OAAO,QAAQ;AAC9B,SAAK,kBAAkB;AAAA,MACrB,sBAAsB,KAAK,OAAO,WAAW,KAAK,OAAO,SAAS;AAAA,IACpE;AACA,SAAK,iBAAiB;AAAA,MACpB,sBAAsB,KAAK,OAAO,UAAU,KAAK,OAAO,SAAS;AAAA,IACnE;AAAA,EACF;AAAA,EAEA,cAAc,YAAuC;AACnD,UAAM,UAA6B;AAAA,MACjC,IAAI,WAAW;AAAA,MACf;AAAA,MACA,YAAY;AAAA,MACZ,QAAQ,CAAC;AAAA,MACT,QAAQ;AAAA,MACR,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IACpC;AACA,SAAK,SAAS,IAAI,QAAQ,IAAI,OAAO;AACrC,IAAAA,SAAO,KAAK,8BAA8B,EAAE,WAAW,QAAQ,GAAG,CAAC;AACnE,WAAO;AAAA,EACT;AAAA,EAEA,WAAW,IAA2C;AACpD,WAAO,KAAK,SAAS,IAAI,EAAE;AAAA,EAC7B;AAAA,EAEA,MAAM,SACJ,WACA,SACoB;AACpB,UAAM,UAAU,KAAK,eAAe,SAAS;AAC7C,YAAQ,SAAS;AACjB,IAAAA,SAAO,KAAK,kBAAkB,EAAE,UAAU,CAAC;AAE3C,UAAM,SAAS,oBAAoB,QAAQ,UAAU;AACrD,UAAM,SAAS,MAAM,KAAK,gBAAgB,IAAI;AAAA,MAC5C;AAAA,MACA,SAAS,KAAK;AAAA,MACd,WAAW,KAAK,OAAO;AAAA,MACvB,eAAe,CAAC,QAAqB;AACnC,kBAAU,EAAE,MAAM,aAAa,MAAM,IAAI,CAAC;AAAA,MAC5C;AAAA,IACF,CAAC;AAED,QAAI,OAAO,SAAS;AAClB,cAAQ,aAAa,OAAO;AAC5B,cAAQ,qBAAqB,OAAO;AACpC,cAAQ,SAAS;AACjB,gBAAU,EAAE,MAAM,gBAAgB,MAAM,EAAE,KAAK,OAAO,OAAO,EAAE,CAAC;AAAA,IAClE,OAAO;AACL,cAAQ,SAAS;AACjB,cAAQ,QAAQ,OAAO;AACvB,gBAAU,EAAE,MAAM,SAAS,MAAM,EAAE,SAAS,OAAO,OAAO,EAAE,CAAC;AAAA,IAC/D;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,OACJ,WACA,SACoB;AACpB,UAAM,UAAU,KAAK,eAAe,SAAS;AAC7C,UAAM,WAAW,QAAQ,OAAO,SAAS;AACzC,YAAQ,SAAS;AACjB,IAAAA,SAAO,KAAK,iBAAiB,EAAE,WAAW,OAAO,SAAS,CAAC;AAC3D,cAAU,EAAE,MAAM,eAAe,MAAM,EAAE,OAAO,UAAU,OAAO,SAAS,GAAG,OAAO,SAAS,CAAC;AAE9F,UAAM,SAAS,kBAAkB,QAAQ,YAAY,QAAQ;AAC7D,UAAM,SAAS,MAAM,KAAK,eAAe,IAAI;AAAA,MAC3C;AAAA,MACA,SAAS,KAAK;AAAA,MACd,WAAW,KAAK,OAAO;AAAA,MACvB,eAAe,CAAC,QAAqB;AACnC,kBAAU,EAAE,MAAM,gBAAgB,MAAM,KAAK,OAAO,SAAS,CAAC;AAAA,MAChE;AAAA,IACF,CAAC;AAED,QAAI,OAAO,SAAS;AAClB,cAAQ,OAAO,KAAK;AAAA,QAClB,OAAO;AAAA,QACP,WAAW,OAAO;AAAA,QAClB,YAAY;AAAA,MACd,CAAC;AACD,cAAQ,SAAS;AACjB,gBAAU,EAAE,MAAM,mBAAmB,MAAM,EAAE,OAAO,UAAU,WAAW,OAAO,OAAO,GAAG,OAAO,SAAS,CAAC;AAAA,IAC7G,OAAO;AACL,cAAQ,SAAS;AACjB,cAAQ,QAAQ,OAAO;AACvB,gBAAU,EAAE,MAAM,SAAS,MAAM,EAAE,SAAS,OAAO,QAAQ,OAAO,SAAS,GAAG,OAAO,SAAS,CAAC;AAAA,IACjG;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,OACJ,WACA,SACoB;AACpB,UAAM,UAAU,KAAK,eAAe,SAAS;AAC7C,UAAM,eAAe,QAAQ,OAAO,QAAQ,OAAO,SAAS,CAAC;AAC7D,QAAI,CAAC,cAAc;AACjB,YAAM,IAAI,MAAM,gCAAgC;AAAA,IAClD;AAEA,YAAQ,SAAS;AACjB,IAAAA,SAAO,KAAK,gBAAgB,EAAE,WAAW,OAAO,aAAa,MAAM,CAAC;AAEpE,UAAM,SAAS,kBAAkB,aAAa,SAAS;AACvD,UAAM,SAAS,MAAM,KAAK,gBAAgB,IAAI;AAAA,MAC5C;AAAA,MACA,SAAS,KAAK;AAAA,MACd,WAAW,KAAK,OAAO;AAAA,MACvB,WAAW,QAAQ;AAAA,MACnB,iBAAiB,CAAC,CAAC,QAAQ;AAAA,MAC3B,eAAe,CAAC,QAAqB;AACnC,kBAAU,EAAE,MAAM,aAAa,MAAM,KAAK,OAAO,aAAa,MAAM,CAAC;AAAA,MACvE;AAAA,IACF,CAAC;AAED,QAAI,OAAO,SAAS;AAClB,mBAAa,aAAa,OAAO;AACjC,cAAQ,aAAa,OAAO;AAC5B,cAAQ,qBAAqB,OAAO,aAAa,QAAQ;AACzD,cAAQ,SAAS;AACjB,gBAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM,EAAE,OAAO,aAAa,OAAO,KAAK,OAAO,OAAO;AAAA,QACtD,OAAO,aAAa;AAAA,MACtB,CAAC;AAAA,IACH,OAAO;AACL,cAAQ,SAAS;AACjB,cAAQ,QAAQ,OAAO;AACvB,gBAAU,EAAE,MAAM,SAAS,MAAM,EAAE,SAAS,OAAO,QAAQ,OAAO,aAAa,MAAM,GAAG,OAAO,aAAa,MAAM,CAAC;AAAA,IACrH;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,WACJ,WACA,QACA,SACe;AACf,UAAM,YAAY,KAAK,IAAI,UAAU,KAAK,OAAO,qBAAqB,KAAK,OAAO,mBAAmB;AACrG,UAAM,UAAU,KAAK,eAAe,SAAS;AAE7C,QAAI,CAAC,QAAQ,YAAY;AACvB,YAAM,KAAK,SAAS,WAAW,OAAO;AACtC,UAAI,QAAQ,WAAW,QAAS;AAAA,IAClC;AAEA,aAAS,IAAI,GAAG,IAAI,WAAW,KAAK;AAClC,YAAM,eAAe,MAAM,KAAK,OAAO,WAAW,OAAO;AACzD,UAAI,CAAC,aAAa,QAAS;AAE3B,YAAM,eAAe,MAAM,KAAK,OAAO,WAAW,OAAO;AACzD,UAAI,CAAC,aAAa,QAAS;AAAA,IAC7B;AAEA,QAAI,QAAQ,WAAW,SAAS;AAC9B,cAAQ,SAAS;AAAA,IACnB;AAAA,EACF;AAAA,EAEQ,eAAe,IAA+B;AACpD,UAAM,UAAU,KAAK,SAAS,IAAI,EAAE;AACpC,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,iCAAiC,EAAE,EAAE;AAAA,IACvD;AACA,WAAO;AAAA,EACT;AACF;","names":["logger","logger","logger","logger","path","IssueState","logger","fs","path","logger","path","fs","fs","path","path","path","fs","fs","path","path","fs","path","fs","fs","path","path","fs","logger","path","logger","DEFAULT_OPTIONS","path","fs","path","logger","fs","path","logger","logger","logger","logger","logger","logger","path","fs","logger"]}