@iloom/cli 0.9.1 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +179 -41
- package/dist/{BranchNamingService-K6XNWQ6C.js → BranchNamingService-ECJHBB67.js} +2 -2
- package/dist/ClaudeContextManager-QXX6ZFST.js +14 -0
- package/dist/ClaudeService-NJNK2SUH.js +13 -0
- package/dist/{GitHubService-O7T6CFAJ.js → GitHubService-MEHKHUQP.js} +4 -4
- package/dist/IssueTrackerFactory-NG53YX5S.js +14 -0
- package/dist/{LoomLauncher-3I47SUPV.js → LoomLauncher-L64HHS3T.js} +9 -9
- package/dist/{MetadataManager-W3C54UYT.js → MetadataManager-5QZSTKNN.js} +2 -2
- package/dist/{ProjectCapabilityDetector-N5L7T4IY.js → ProjectCapabilityDetector-5KSYUTBJ.js} +3 -3
- package/dist/{PromptTemplateManager-36YLQRHP.js → PromptTemplateManager-DULSVRRE.js} +2 -2
- package/dist/README.md +179 -41
- package/dist/{SettingsManager-QR7V2IW2.js → SettingsManager-BQDQA3FK.js} +4 -2
- package/dist/agents/iloom-artifact-reviewer.md +11 -0
- package/dist/agents/iloom-code-reviewer.md +14 -0
- package/dist/agents/iloom-issue-analyze-and-plan.md +55 -12
- package/dist/agents/iloom-issue-analyzer.md +49 -6
- package/dist/agents/iloom-issue-complexity-evaluator.md +47 -6
- package/dist/agents/iloom-issue-enhancer.md +86 -7
- package/dist/agents/iloom-issue-implementer.md +48 -7
- package/dist/agents/iloom-issue-planner.md +115 -62
- package/dist/{build-IC4CJRMP.js → build-5GO3XW26.js} +9 -9
- package/dist/{chunk-USSL2X4A.js → chunk-3D7WQM7I.js} +2 -2
- package/dist/chunk-4232AHNQ.js +35 -0
- package/dist/chunk-4232AHNQ.js.map +1 -0
- package/dist/{chunk-QN47QVBX.js → chunk-4WJNIR5O.js} +1 -1
- package/dist/chunk-4WJNIR5O.js.map +1 -0
- package/dist/{chunk-2JPXGGP4.js → chunk-5MWV33NN.js} +4 -4
- package/dist/{chunk-POU2UMWN.js → chunk-6EU6TCF6.js} +10 -10
- package/dist/chunk-6EU6TCF6.js.map +1 -0
- package/dist/{chunk-Y5O2ALDZ.js → chunk-FB47TIJG.js} +29 -11
- package/dist/chunk-FB47TIJG.js.map +1 -0
- package/dist/chunk-HEXKPKCK.js +1396 -0
- package/dist/chunk-HEXKPKCK.js.map +1 -0
- package/dist/{chunk-KAYXR544.js → chunk-J5S7DFYC.js} +2 -2
- package/dist/{chunk-OK7LUTRW.js → chunk-JO2LZ6EQ.js} +476 -5
- package/dist/chunk-JO2LZ6EQ.js.map +1 -0
- package/dist/{chunk-KBEIQP4G.js → chunk-KB64WNBZ.js} +43 -3
- package/dist/chunk-KB64WNBZ.js.map +1 -0
- package/dist/{chunk-Y5HSSIK2.js → chunk-KXDRI47U.js} +71 -13
- package/dist/chunk-KXDRI47U.js.map +1 -0
- package/dist/{chunk-HZXBHMVM.js → chunk-LXLMMXXY.js} +54 -14
- package/dist/chunk-LXLMMXXY.js.map +1 -0
- package/dist/{chunk-H6ST2TGP.js → chunk-MNHZB4Z2.js} +4 -4
- package/dist/{chunk-TL72BGP6.js → chunk-MORRVYPT.js} +2 -2
- package/dist/{chunk-TGRK3CHF.js → chunk-NRSWLOAZ.js} +8 -8
- package/dist/chunk-NRSWLOAZ.js.map +1 -0
- package/dist/{chunk-FO5GGFOV.js → chunk-ONQYPICO.js} +13 -5
- package/dist/chunk-ONQYPICO.js.map +1 -0
- package/dist/{chunk-7ZEHSSUP.js → chunk-P4O6EH46.js} +4 -4
- package/dist/chunk-QZWEJVWV.js +207 -0
- package/dist/chunk-QZWEJVWV.js.map +1 -0
- package/dist/chunk-RSYT7MVI.js +202 -0
- package/dist/chunk-RSYT7MVI.js.map +1 -0
- package/dist/{chunk-OAVJR4PM.js → chunk-RYWFS37M.js} +6 -6
- package/dist/chunk-RYWFS37M.js.map +1 -0
- package/dist/{chunk-B7U6OKUR.js → chunk-SF2P22EE.js} +11 -3
- package/dist/chunk-SF2P22EE.js.map +1 -0
- package/dist/{chunk-MZPRBNYC.js → chunk-SN3SQCFK.js} +10 -8
- package/dist/{chunk-MZPRBNYC.js.map → chunk-SN3SQCFK.js.map} +1 -1
- package/dist/{chunk-4ZIHFUPN.js → chunk-UD3WJDIV.js} +145 -107
- package/dist/chunk-UD3WJDIV.js.map +1 -0
- package/dist/{chunk-3P6J4IZZ.js → chunk-UKBAJ2QQ.js} +61 -7
- package/dist/chunk-UKBAJ2QQ.js.map +1 -0
- package/dist/{chunk-RD7OPXZK.js → chunk-UVD4CZKS.js} +3 -3
- package/dist/chunk-UWGVCXRF.js +207 -0
- package/dist/chunk-UWGVCXRF.js.map +1 -0
- package/dist/{chunk-JT5LZRMI.js → chunk-VECNX6VX.js} +2 -2
- package/dist/{chunk-TRUMP4DA.js → chunk-VG45TUYK.js} +75 -6
- package/dist/chunk-VG45TUYK.js.map +1 -0
- package/dist/{chunk-4GAJJUYS.js → chunk-VGGST52X.js} +2 -2
- package/dist/{chunk-4LKGCFGG.js → chunk-WWKOVDWC.js} +2 -2
- package/dist/{chunk-2HZX6AMR.js → chunk-WY4QBK43.js} +7 -7
- package/dist/chunk-WY4QBK43.js.map +1 -0
- package/dist/chunk-Y4YZTHZE.js +73 -0
- package/dist/chunk-Y4YZTHZE.js.map +1 -0
- package/dist/{chunk-VOGGLPG5.js → chunk-YQ57ORTV.js} +14 -1
- package/dist/chunk-YQ57ORTV.js.map +1 -0
- package/dist/{chunk-XFEK2X2D.js → chunk-YYAKPQBT.js} +73 -20
- package/dist/chunk-YYAKPQBT.js.map +1 -0
- package/dist/{chunk-NTTSUAVM.js → chunk-ZEWU5PZK.js} +2 -2
- package/dist/{chunk-5LVVQGB3.js → chunk-ZHPNZC75.js} +17 -17
- package/dist/chunk-ZHPNZC75.js.map +1 -0
- package/dist/{chunk-I3HMNWQQ.js → chunk-ZW2LKWWE.js} +9 -9
- package/dist/chunk-ZW2LKWWE.js.map +1 -0
- package/dist/{claude-TP2QO3BU.js → claude-P3NQR6IJ.js} +2 -2
- package/dist/{cleanup-D3CSRBBZ.js → cleanup-6UCPVMFG.js} +81 -32
- package/dist/cleanup-6UCPVMFG.js.map +1 -0
- package/dist/cli.js +640 -350
- package/dist/cli.js.map +1 -1
- package/dist/{commit-IWGT42XN.js → commit-L3EPY5QG.js} +23 -21
- package/dist/commit-L3EPY5QG.js.map +1 -0
- package/dist/{compile-EOWJORKO.js → compile-ZS4HYRX5.js} +9 -9
- package/dist/{contribute-WSJTV2RX.js → contribute-ORDDQGSL.js} +14 -6
- package/dist/contribute-ORDDQGSL.js.map +1 -0
- package/dist/{dev-server-Q6M62ATG.js → dev-server-FYZ2AQIH.js} +29 -15
- package/dist/dev-server-FYZ2AQIH.js.map +1 -0
- package/dist/{feedback-QPNDZQRV.js → feedback-TMBXSCM5.js} +15 -15
- package/dist/{git-W3XUIFTR.js → git-ET64COO3.js} +4 -4
- package/dist/hooks/iloom-hook.js +15 -0
- package/dist/ignite-CGOV3TD4.js +1393 -0
- package/dist/ignite-CGOV3TD4.js.map +1 -0
- package/dist/index.d.ts +397 -53
- package/dist/index.js +1178 -40
- package/dist/index.js.map +1 -1
- package/dist/{init-ALYWKNWG.js → init-GFQ5W7GK.js} +57 -21
- package/dist/init-GFQ5W7GK.js.map +1 -0
- package/dist/issues-T4ZZSPEG.js +179 -0
- package/dist/issues-T4ZZSPEG.js.map +1 -0
- package/dist/{lint-IHUH45OC.js → lint-6TQXDZ3T.js} +9 -9
- package/dist/mcp/issue-management-server.js +2472 -257
- package/dist/mcp/issue-management-server.js.map +1 -1
- package/dist/mcp/recap-server.js +144 -21
- package/dist/mcp/recap-server.js.map +1 -1
- package/dist/{neon-helpers-VVFFTLXE.js → neon-helpers-CQN2PB4S.js} +3 -3
- package/dist/neon-helpers-CQN2PB4S.js.map +1 -0
- package/dist/{open-KWOV2OFO.js → open-5QZGXQRF.js} +15 -15
- package/dist/open-5QZGXQRF.js.map +1 -0
- package/dist/{plan-BRJBFJHF.js → plan-U7ZQWLFY.js} +41 -25
- package/dist/plan-U7ZQWLFY.js.map +1 -0
- package/dist/{projects-LH362JZQ.js → projects-2UOXFLNZ.js} +4 -4
- package/dist/prompts/CLAUDE.md +62 -0
- package/dist/prompts/init-prompt.txt +386 -47
- package/dist/prompts/issue-prompt.txt +427 -54
- package/dist/prompts/plan-prompt.txt +97 -16
- package/dist/prompts/pr-prompt.txt +44 -1
- package/dist/prompts/regular-prompt.txt +42 -1
- package/dist/prompts/session-summary-prompt.txt +14 -0
- package/dist/prompts/swarm-orchestrator-prompt.txt +437 -0
- package/dist/{rebase-AJOJOZUG.js → rebase-DWIB77KV.js} +10 -10
- package/dist/{recap-GKJXMDXW.js → recap-MX63HAKV.js} +47 -19
- package/dist/recap-MX63HAKV.js.map +1 -0
- package/dist/{run-QEUVZF7J.js → run-O3TFNQFC.js} +15 -15
- package/dist/run-O3TFNQFC.js.map +1 -0
- package/dist/schema/package-iloom.schema.json +58 -0
- package/dist/schema/settings.schema.json +130 -15
- package/dist/{shell-DAAVG4YN.js → shell-G6VC2CYR.js} +14 -7
- package/dist/shell-G6VC2CYR.js.map +1 -0
- package/dist/{summary-ZKOA35PT.js → summary-FWHAX55O.js} +27 -25
- package/dist/summary-FWHAX55O.js.map +1 -0
- package/dist/{test-5GPWWO3P.js → test-F7JNJZYP.js} +9 -9
- package/dist/{test-git-EJUKDB7F.js → test-git-BTAOIUE2.js} +4 -4
- package/dist/test-jira-CHYNV33F.js +96 -0
- package/dist/test-jira-CHYNV33F.js.map +1 -0
- package/dist/{test-prefix-23TOBUXY.js → test-prefix-Q6TFSU6F.js} +4 -4
- package/dist/{test-webserver-CKROHFBQ.js → test-webserver-EONCG7E7.js} +6 -6
- package/dist/{vscode-6TOLFCI2.js → vscode-VA5X4P25.js} +7 -7
- package/package.json +5 -1
- package/dist/ClaudeContextManager-X2Y72GRL.js +0 -14
- package/dist/ClaudeService-7P32TTES.js +0 -13
- package/dist/chunk-2HZX6AMR.js.map +0 -1
- package/dist/chunk-3P6J4IZZ.js.map +0 -1
- package/dist/chunk-4ZIHFUPN.js.map +0 -1
- package/dist/chunk-5LVVQGB3.js.map +0 -1
- package/dist/chunk-B7U6OKUR.js.map +0 -1
- package/dist/chunk-ENGCJIYQ.js +0 -520
- package/dist/chunk-ENGCJIYQ.js.map +0 -1
- package/dist/chunk-FO5GGFOV.js.map +0 -1
- package/dist/chunk-HZXBHMVM.js.map +0 -1
- package/dist/chunk-I3HMNWQQ.js.map +0 -1
- package/dist/chunk-J7FJ6PUT.js +0 -121
- package/dist/chunk-J7FJ6PUT.js.map +0 -1
- package/dist/chunk-KBEIQP4G.js.map +0 -1
- package/dist/chunk-OAVJR4PM.js.map +0 -1
- package/dist/chunk-OK7LUTRW.js.map +0 -1
- package/dist/chunk-POU2UMWN.js.map +0 -1
- package/dist/chunk-QN47QVBX.js.map +0 -1
- package/dist/chunk-TGRK3CHF.js.map +0 -1
- package/dist/chunk-TRUMP4DA.js.map +0 -1
- package/dist/chunk-VOGGLPG5.js.map +0 -1
- package/dist/chunk-XFEK2X2D.js.map +0 -1
- package/dist/chunk-Y5HSSIK2.js.map +0 -1
- package/dist/chunk-Y5O2ALDZ.js.map +0 -1
- package/dist/cleanup-D3CSRBBZ.js.map +0 -1
- package/dist/commit-IWGT42XN.js.map +0 -1
- package/dist/contribute-WSJTV2RX.js.map +0 -1
- package/dist/dev-server-Q6M62ATG.js.map +0 -1
- package/dist/ignite-OPO6EDYT.js +0 -784
- package/dist/ignite-OPO6EDYT.js.map +0 -1
- package/dist/init-ALYWKNWG.js.map +0 -1
- package/dist/issues-L7TBUPXT.js +0 -116
- package/dist/issues-L7TBUPXT.js.map +0 -1
- package/dist/open-KWOV2OFO.js.map +0 -1
- package/dist/plan-BRJBFJHF.js.map +0 -1
- package/dist/recap-GKJXMDXW.js.map +0 -1
- package/dist/run-QEUVZF7J.js.map +0 -1
- package/dist/shell-DAAVG4YN.js.map +0 -1
- package/dist/summary-ZKOA35PT.js.map +0 -1
- /package/dist/{BranchNamingService-K6XNWQ6C.js.map → BranchNamingService-ECJHBB67.js.map} +0 -0
- /package/dist/{ClaudeContextManager-X2Y72GRL.js.map → ClaudeContextManager-QXX6ZFST.js.map} +0 -0
- /package/dist/{ClaudeService-7P32TTES.js.map → ClaudeService-NJNK2SUH.js.map} +0 -0
- /package/dist/{GitHubService-O7T6CFAJ.js.map → GitHubService-MEHKHUQP.js.map} +0 -0
- /package/dist/{MetadataManager-W3C54UYT.js.map → IssueTrackerFactory-NG53YX5S.js.map} +0 -0
- /package/dist/{LoomLauncher-3I47SUPV.js.map → LoomLauncher-L64HHS3T.js.map} +0 -0
- /package/dist/{ProjectCapabilityDetector-N5L7T4IY.js.map → MetadataManager-5QZSTKNN.js.map} +0 -0
- /package/dist/{PromptTemplateManager-36YLQRHP.js.map → ProjectCapabilityDetector-5KSYUTBJ.js.map} +0 -0
- /package/dist/{SettingsManager-QR7V2IW2.js.map → PromptTemplateManager-DULSVRRE.js.map} +0 -0
- /package/dist/{claude-TP2QO3BU.js.map → SettingsManager-BQDQA3FK.js.map} +0 -0
- /package/dist/{build-IC4CJRMP.js.map → build-5GO3XW26.js.map} +0 -0
- /package/dist/{chunk-USSL2X4A.js.map → chunk-3D7WQM7I.js.map} +0 -0
- /package/dist/{chunk-2JPXGGP4.js.map → chunk-5MWV33NN.js.map} +0 -0
- /package/dist/{chunk-KAYXR544.js.map → chunk-J5S7DFYC.js.map} +0 -0
- /package/dist/{chunk-H6ST2TGP.js.map → chunk-MNHZB4Z2.js.map} +0 -0
- /package/dist/{chunk-TL72BGP6.js.map → chunk-MORRVYPT.js.map} +0 -0
- /package/dist/{chunk-7ZEHSSUP.js.map → chunk-P4O6EH46.js.map} +0 -0
- /package/dist/{chunk-RD7OPXZK.js.map → chunk-UVD4CZKS.js.map} +0 -0
- /package/dist/{chunk-JT5LZRMI.js.map → chunk-VECNX6VX.js.map} +0 -0
- /package/dist/{chunk-4GAJJUYS.js.map → chunk-VGGST52X.js.map} +0 -0
- /package/dist/{chunk-4LKGCFGG.js.map → chunk-WWKOVDWC.js.map} +0 -0
- /package/dist/{chunk-NTTSUAVM.js.map → chunk-ZEWU5PZK.js.map} +0 -0
- /package/dist/{git-W3XUIFTR.js.map → claude-P3NQR6IJ.js.map} +0 -0
- /package/dist/{compile-EOWJORKO.js.map → compile-ZS4HYRX5.js.map} +0 -0
- /package/dist/{feedback-QPNDZQRV.js.map → feedback-TMBXSCM5.js.map} +0 -0
- /package/dist/{neon-helpers-VVFFTLXE.js.map → git-ET64COO3.js.map} +0 -0
- /package/dist/{lint-IHUH45OC.js.map → lint-6TQXDZ3T.js.map} +0 -0
- /package/dist/{projects-LH362JZQ.js.map → projects-2UOXFLNZ.js.map} +0 -0
- /package/dist/{rebase-AJOJOZUG.js.map → rebase-DWIB77KV.js.map} +0 -0
- /package/dist/{test-5GPWWO3P.js.map → test-F7JNJZYP.js.map} +0 -0
- /package/dist/{test-git-EJUKDB7F.js.map → test-git-BTAOIUE2.js.map} +0 -0
- /package/dist/{test-prefix-23TOBUXY.js.map → test-prefix-Q6TFSU6F.js.map} +0 -0
- /package/dist/{test-webserver-CKROHFBQ.js.map → test-webserver-EONCG7E7.js.map} +0 -0
- /package/dist/{vscode-6TOLFCI2.js.map → vscode-VA5X4P25.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/linear.ts","../src/types/linear.ts","../src/lib/providers/jira/JiraApiClient.ts","../src/lib/providers/jira/AdfMarkdownConverter.ts","../src/lib/providers/jira/JiraIssueTracker.ts"],"sourcesContent":["/**\n * Linear SDK utilities\n * Wrapper functions for the @linear/sdk\n */\n\nimport { LinearClient, IssueRelationType } from '@linear/sdk'\nimport type { LinearIssue, LinearComment } from '../types/linear.js'\nimport { LinearServiceError } from '../types/linear.js'\nimport { logger } from './logger.js'\n\n/**\n * Slugify a title for use in Linear URLs\n * Converts to lowercase, replaces non-alphanumeric with hyphens, truncates to reasonable length\n * @param title - Issue title\n * @param maxLength - Maximum slug length (default: 50)\n * @returns Slugified title\n */\nexport function slugifyTitle(title: string, maxLength: number = 50): string {\n // Convert to lowercase, replace non-alphanumeric chars with hyphens\n const slug = title\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '') // trim leading/trailing hyphens\n\n // If already short enough, return as-is\n if (slug.length <= maxLength) {\n return slug\n }\n\n // Split by hyphens and rebuild until we hit the limit\n const parts = slug.split('-')\n let result = ''\n for (const part of parts) {\n const candidate = result ? `${result}-${part}` : part\n if (candidate.length > maxLength) {\n break\n }\n result = candidate\n }\n\n return result || slug.slice(0, maxLength) // fallback if first part is too long\n}\n\n/**\n * Build a Linear issue URL with optional title slug\n * @param identifier - Issue identifier (e.g., \"ENG-123\")\n * @param title - Optional issue title for slug\n * @returns Linear URL\n */\nexport function buildLinearIssueUrl(identifier: string, title?: string): string {\n const base = `https://linear.app/issue/${identifier}`\n if (title) {\n const slug = slugifyTitle(title)\n return slug ? `${base}/${slug}` : base\n }\n return base\n}\n\n/**\n * Get Linear API token from environment\n * @returns API token\n * @throws LinearServiceError if token not found\n */\nfunction getLinearApiToken(): string {\n const token = process.env.LINEAR_API_TOKEN\n if (!token) {\n throw new LinearServiceError(\n 'UNAUTHORIZED',\n 'LINEAR_API_TOKEN not set. Configure in settings.local.json or set environment variable.',\n )\n }\n return token\n}\n\n/**\n * Create a Linear SDK client instance\n * @param apiToken - Optional API token (takes precedence over env var)\n * @returns Configured LinearClient\n */\nfunction createLinearClient(apiToken?: string): LinearClient {\n const token = apiToken ?? getLinearApiToken()\n return new LinearClient({ apiKey: token })\n}\n\n/**\n * Handle SDK errors and convert to LinearServiceError\n * @param error - Error from SDK\n * @param context - Context string for debugging\n * @throws LinearServiceError\n */\nfunction handleLinearError(error: unknown, context: string): never {\n logger.debug(`${context}: Handling error`, { error })\n\n // SDK errors typically have a message property\n const errorMessage = error instanceof Error ? error.message : String(error)\n\n // Map common error patterns\n if (errorMessage.includes('not found') || errorMessage.includes('Not found')) {\n throw new LinearServiceError('NOT_FOUND', 'Linear issue or resource not found', { error })\n }\n\n if (\n errorMessage.includes('unauthorized') ||\n errorMessage.includes('Unauthorized') ||\n errorMessage.includes('Invalid API key')\n ) {\n throw new LinearServiceError(\n 'UNAUTHORIZED',\n 'Linear authentication failed. Check LINEAR_API_TOKEN.',\n { error },\n )\n }\n\n if (errorMessage.includes('rate limit')) {\n throw new LinearServiceError('RATE_LIMITED', 'Linear API rate limit exceeded', { error })\n }\n\n // Generic SDK error\n throw new LinearServiceError('CLI_ERROR', `Linear SDK error: ${errorMessage}`, { error })\n}\n\n/**\n * Fetch a Linear issue by identifier\n * @param identifier - Linear issue identifier (e.g., \"ENG-123\")\n * @returns Linear issue details\n * @throws LinearServiceError if issue not found or SDK error\n */\nexport async function fetchLinearIssue(identifier: string): Promise<LinearIssue> {\n try {\n logger.debug(`Fetching Linear issue: ${identifier}`)\n const client = createLinearClient()\n const issue = await client.issue(identifier)\n\n if (!issue) {\n throw new LinearServiceError('NOT_FOUND', `Linear issue ${identifier} not found`)\n }\n\n // Convert SDK issue to our LinearIssue type\n const result: LinearIssue = {\n id: issue.id,\n identifier: issue.identifier,\n title: issue.title,\n url: issue.url,\n createdAt: issue.createdAt.toISOString(),\n updatedAt: issue.updatedAt.toISOString(),\n }\n\n // Add optional fields if present\n if (issue.description) {\n result.description = issue.description\n }\n\n if (issue.state) {\n const state = await issue.state\n if (state?.name) {\n result.state = state.name\n }\n }\n\n return result\n } catch (error) {\n if (error instanceof LinearServiceError) {\n throw error\n }\n handleLinearError(error, 'fetchLinearIssue')\n }\n}\n\n/**\n * Create a new Linear issue\n * @param title - Issue title\n * @param body - Issue description (markdown)\n * @param teamKey - Team key (e.g., \"ENG\", \"PLAT\")\n * @param labels - Optional label names to apply\n * @returns Created issue identifier and URL\n * @throws LinearServiceError on creation failure\n */\nexport async function createLinearIssue(\n title: string,\n body: string,\n teamKey: string,\n _labels?: string[],\n): Promise<{ identifier: string; url: string }> {\n try {\n logger.debug(`Creating Linear issue in team ${teamKey}: ${title}`)\n const client = createLinearClient()\n\n // Get team by key\n const teams = await client.teams()\n const team = teams.nodes.find((t) => t.key === teamKey)\n\n if (!team) {\n throw new LinearServiceError('NOT_FOUND', `Linear team ${teamKey} not found`)\n }\n\n // Create issue\n const issueInput: { teamId: string; title: string; description?: string } = {\n teamId: team.id,\n title,\n }\n\n if (body) {\n issueInput.description = body\n }\n\n const payload = await client.createIssue(issueInput)\n\n const issue = await payload.issue\n\n if (!issue) {\n throw new LinearServiceError('CLI_ERROR', 'Failed to create Linear issue')\n }\n\n // Construct URL\n const url = issue.url ?? buildLinearIssueUrl(issue.identifier, title)\n\n return {\n identifier: issue.identifier,\n url,\n }\n } catch (error) {\n if (error instanceof LinearServiceError) {\n throw error\n }\n handleLinearError(error, 'createLinearIssue')\n }\n}\n\n/**\n * Create a child issue linked to a parent issue\n * Linear supports atomic creation with parentId field\n * @param title - Issue title\n * @param body - Issue description (markdown)\n * @param teamKey - Team key (e.g., \"ENG\")\n * @param parentId - Parent issue UUID (from issue.id, not identifier)\n * @param labels - Optional label names to apply\n * @returns Created issue identifier and URL\n * @throws LinearServiceError on creation failure\n */\nexport async function createLinearChildIssue(\n title: string,\n body: string,\n teamKey: string,\n parentId: string,\n _labels?: string[],\n): Promise<{ identifier: string; url: string }> {\n try {\n logger.debug(`Creating Linear child issue in team ${teamKey}: ${title}`)\n const client = createLinearClient()\n\n // Get team by key\n const teams = await client.teams()\n const team = teams.nodes.find((t) => t.key === teamKey)\n\n if (!team) {\n throw new LinearServiceError('NOT_FOUND', `Linear team ${teamKey} not found`)\n }\n\n // Create issue with parentId for atomic parent-child relationship\n const issueInput: { teamId: string; title: string; description?: string; parentId: string } = {\n teamId: team.id,\n title,\n parentId, // UUID of parent issue\n }\n\n if (body) {\n issueInput.description = body\n }\n\n const payload = await client.createIssue(issueInput)\n\n const issue = await payload.issue\n\n if (!issue) {\n throw new LinearServiceError('CLI_ERROR', 'Failed to create Linear child issue')\n }\n\n // Construct URL\n const url = issue.url ?? buildLinearIssueUrl(issue.identifier, title)\n\n return {\n identifier: issue.identifier,\n url,\n }\n } catch (error) {\n if (error instanceof LinearServiceError) {\n throw error\n }\n handleLinearError(error, 'createLinearChildIssue')\n }\n}\n\n/**\n * Create a comment on a Linear issue\n * @param identifier - Linear issue identifier (e.g., \"ENG-123\")\n * @param body - Comment body (markdown)\n * @returns Created comment details\n * @throws LinearServiceError on creation failure\n */\nexport async function createLinearComment(\n identifier: string,\n body: string,\n): Promise<LinearComment> {\n try {\n logger.debug(`Creating comment on Linear issue ${identifier}`)\n const client = createLinearClient()\n\n // Get issue by identifier to get its ID\n const issue = await client.issue(identifier)\n if (!issue) {\n throw new LinearServiceError('NOT_FOUND', `Linear issue ${identifier} not found`)\n }\n\n // Create comment using issue ID\n const payload = await client.createComment({\n issueId: issue.id,\n body,\n })\n\n const comment = await payload.comment\n\n if (!comment) {\n throw new LinearServiceError('CLI_ERROR', 'Failed to create Linear comment')\n }\n\n return {\n id: comment.id,\n body: comment.body,\n createdAt: comment.createdAt.toISOString(),\n updatedAt: comment.updatedAt.toISOString(),\n url: comment.url,\n }\n } catch (error) {\n if (error instanceof LinearServiceError) {\n throw error\n }\n handleLinearError(error, 'createLinearComment')\n }\n}\n\n/**\n * Update a Linear issue's workflow state\n * @param identifier - Linear issue identifier (e.g., \"ENG-123\")\n * @param stateName - Target state name (e.g., \"In Progress\", \"Done\")\n * @throws LinearServiceError on update failure\n */\nexport async function updateLinearIssueState(\n identifier: string,\n stateName: string,\n): Promise<void> {\n try {\n logger.debug(`Updating Linear issue ${identifier} state to: ${stateName}`)\n const client = createLinearClient()\n\n // Get issue by identifier\n const issue = await client.issue(identifier)\n if (!issue) {\n throw new LinearServiceError('NOT_FOUND', `Linear issue ${identifier} not found`)\n }\n\n // Get team to find state\n const team = await issue.team\n if (!team) {\n throw new LinearServiceError('CLI_ERROR', 'Issue has no team')\n }\n\n // Find state by name\n const states = await team.states()\n const state = states.nodes.find((s) => s.name === stateName)\n\n if (!state) {\n throw new LinearServiceError(\n 'NOT_FOUND',\n `State \"${stateName}\" not found in team ${team.key}`,\n )\n }\n\n // Update issue state\n await client.updateIssue(issue.id, {\n stateId: state.id,\n })\n } catch (error) {\n if (error instanceof LinearServiceError) {\n throw error\n }\n handleLinearError(error, 'updateLinearIssueState')\n }\n}\n\n/**\n * Edit a Linear issue's properties (title, description)\n * @param identifier - Linear issue identifier (e.g., \"ENG-123\")\n * @param updates - Fields to update\n * @throws LinearServiceError on update failure\n */\nexport async function editLinearIssue(\n identifier: string,\n updates: { title?: string; description?: string },\n): Promise<void> {\n try {\n logger.debug(`Editing Linear issue ${identifier}`, { updates })\n const client = createLinearClient()\n\n // Get issue by identifier\n const issue = await client.issue(identifier)\n if (!issue) {\n throw new LinearServiceError('NOT_FOUND', `Linear issue ${identifier} not found`)\n }\n\n // Build update payload\n const updatePayload: { title?: string; description?: string } = {}\n if (updates.title !== undefined) {\n updatePayload.title = updates.title\n }\n if (updates.description !== undefined) {\n updatePayload.description = updates.description\n }\n\n if (Object.keys(updatePayload).length > 0) {\n await client.updateIssue(issue.id, updatePayload)\n }\n } catch (error) {\n if (error instanceof LinearServiceError) {\n throw error\n }\n handleLinearError(error, 'editLinearIssue')\n }\n}\n\n/**\n * Get a specific comment by ID\n * @param commentId - Linear comment UUID\n * @returns Comment details\n * @throws LinearServiceError if comment not found\n */\nexport async function getLinearComment(commentId: string): Promise<LinearComment> {\n try {\n logger.debug(`Fetching Linear comment: ${commentId}`)\n const client = createLinearClient()\n const comment = await client.comment({ id: commentId })\n\n if (!comment) {\n throw new LinearServiceError('NOT_FOUND', `Linear comment ${commentId} not found`)\n }\n\n return {\n id: comment.id,\n body: comment.body,\n createdAt: comment.createdAt.toISOString(),\n updatedAt: comment.updatedAt.toISOString(),\n url: comment.url,\n }\n } catch (error) {\n if (error instanceof LinearServiceError) {\n throw error\n }\n handleLinearError(error, 'getLinearComment')\n }\n}\n\n/**\n * Update an existing comment\n * @param commentId - Linear comment UUID\n * @param body - New comment body (markdown)\n * @returns Updated comment details\n * @throws LinearServiceError on update failure\n */\nexport async function updateLinearComment(\n commentId: string,\n body: string,\n): Promise<LinearComment> {\n try {\n logger.debug(`Updating Linear comment: ${commentId}`)\n const client = createLinearClient()\n\n const payload = await client.updateComment(commentId, { body })\n const comment = await payload.comment\n\n if (!comment) {\n throw new LinearServiceError('CLI_ERROR', 'Failed to update Linear comment')\n }\n\n return {\n id: comment.id,\n body: comment.body,\n createdAt: comment.createdAt.toISOString(),\n updatedAt: comment.updatedAt.toISOString(),\n url: comment.url,\n }\n } catch (error) {\n if (error instanceof LinearServiceError) {\n throw error\n }\n handleLinearError(error, 'updateLinearComment')\n }\n}\n\n/**\n * Fetch all comments for a Linear issue\n * @param identifier - Linear issue identifier (e.g., \"ENG-123\")\n * @returns Array of comments\n * @throws LinearServiceError on fetch failure\n */\nexport async function fetchLinearIssueComments(identifier: string): Promise<LinearComment[]> {\n try {\n logger.debug(`Fetching comments for Linear issue: ${identifier}`)\n const client = createLinearClient()\n\n // Get issue by identifier\n const issue = await client.issue(identifier)\n if (!issue) {\n throw new LinearServiceError('NOT_FOUND', `Linear issue ${identifier} not found`)\n }\n\n // Fetch comments\n const comments = await issue.comments({ first: 100 })\n\n return comments.nodes.map((comment) => ({\n id: comment.id,\n body: comment.body,\n createdAt: comment.createdAt.toISOString(),\n updatedAt: comment.updatedAt.toISOString(),\n url: comment.url,\n }))\n } catch (error) {\n if (error instanceof LinearServiceError) {\n throw error\n }\n handleLinearError(error, 'fetchLinearIssueComments')\n }\n}\n\n/**\n * Get child issues of a parent Linear issue\n * @param identifier - Linear issue identifier (e.g., \"ENG-123\")\n * @param options - Optional settings\n * @param options.apiToken - Optional API token (takes precedence over env var)\n * @returns Array of child issues\n * @throws LinearServiceError on fetch failure\n */\nexport async function getLinearChildIssues(\n identifier: string,\n options?: { apiToken?: string },\n): Promise<Array<{ id: string; title: string; url: string; state: string }>> {\n try {\n logger.debug(`Fetching child issues for Linear issue: ${identifier}`)\n const client = createLinearClient(options?.apiToken)\n\n // Get issue by identifier\n const issue = await client.issue(identifier)\n if (!issue) {\n throw new LinearServiceError('NOT_FOUND', `Linear issue ${identifier} not found`)\n }\n\n // Fetch child issues\n const children = await issue.children({ first: 100 })\n\n // Build results, fetching state in parallel\n const results = await Promise.all(\n children.nodes.map(async (child) => {\n const stateObj = await child.state\n const state = stateObj?.name ?? 'unknown'\n\n return {\n id: child.identifier,\n title: child.title,\n url: child.url,\n state,\n }\n }),\n )\n\n return results\n } catch (error) {\n if (error instanceof LinearServiceError) {\n throw error\n }\n handleLinearError(error, 'getLinearChildIssues')\n }\n}\n\n// Linear Issue Dependency Operations\n\n/**\n * Dependency result for Linear issues\n */\nexport interface LinearDependencyResult {\n id: string\n title: string\n url: string\n state: string\n}\n\n/**\n * Create a blocking relationship between two issues\n * @param blockingIssueId - UUID of the issue that blocks (the blocker)\n * @param blockedIssueId - UUID of the issue being blocked\n * @throws LinearServiceError on creation failure\n */\nexport async function createLinearIssueRelation(\n blockingIssueId: string,\n blockedIssueId: string,\n): Promise<void> {\n try {\n logger.debug(`Creating Linear issue relation: ${blockingIssueId} blocks ${blockedIssueId}`)\n const client = createLinearClient()\n\n // Create a \"blocks\" relation from blockingIssue to blockedIssue\n // In Linear, the relation is created on the blocking issue pointing to the blocked issue\n const payload = await client.createIssueRelation({\n issueId: blockingIssueId,\n relatedIssueId: blockedIssueId,\n type: IssueRelationType.Blocks,\n })\n\n if (!payload.success) {\n throw new LinearServiceError('CLI_ERROR', 'Failed to create Linear issue relation')\n }\n } catch (error) {\n if (error instanceof LinearServiceError) {\n throw error\n }\n handleLinearError(error, 'createLinearIssueRelation')\n }\n}\n\n/**\n * Get dependencies for a Linear issue\n * @param identifier - Linear issue identifier (e.g., \"ENG-123\")\n * @param direction - 'blocking' for issues this blocks, 'blocked_by' for blockers, 'both' for all\n * @returns Object with blocking and blockedBy arrays\n * @throws LinearServiceError on fetch failure\n */\nexport async function getLinearIssueDependencies(\n identifier: string,\n direction: 'blocking' | 'blocked_by' | 'both',\n): Promise<{ blocking: LinearDependencyResult[]; blockedBy: LinearDependencyResult[] }> {\n try {\n logger.debug(`Fetching Linear issue dependencies: ${identifier} (direction: ${direction})`)\n const client = createLinearClient()\n\n // Get issue by identifier\n const issue = await client.issue(identifier)\n if (!issue) {\n throw new LinearServiceError('NOT_FOUND', `Linear issue ${identifier} not found`)\n }\n\n // Fetch relations and inverse relations in parallel\n const [relations, inverseRelations] = await Promise.all([\n issue.relations(),\n issue.inverseRelations(),\n ])\n\n const blocking: LinearDependencyResult[] = []\n const blockedBy: LinearDependencyResult[] = []\n\n // Helper to build dependency result from a resolved issue\n const buildDependencyResult = async (\n relatedIssue: { identifier: string; title: string; url: string; state: unknown } | null | undefined,\n ): Promise<LinearDependencyResult | null> => {\n if (!relatedIssue) return null\n\n const stateObj = await (relatedIssue.state as Promise<{ name?: string } | null | undefined>)\n const state = stateObj?.name ?? 'unknown'\n\n return {\n id: relatedIssue.identifier,\n title: relatedIssue.title,\n url: relatedIssue.url,\n state,\n }\n }\n\n // Process blocking relations (this issue blocks the related issue)\n // relations with type 'blocks' mean this issue blocks the related issue\n if (direction === 'blocking' || direction === 'both') {\n const blockingRelations = relations.nodes.filter(\n (r) => r.type === IssueRelationType.Blocks,\n )\n // Resolve all related issues in parallel, then build results\n // Filter out undefined relatedIssue before Promise.all (LinearFetch<Issue> | undefined)\n const relatedIssuePromises = blockingRelations\n .map((r) => r.relatedIssue)\n .filter((p): p is NonNullable<typeof p> => p !== undefined)\n const relatedIssues = await Promise.all(relatedIssuePromises)\n const blockingResults = await Promise.all(\n relatedIssues.map((issue) => buildDependencyResult(issue)),\n )\n blocking.push(...blockingResults.filter((r): r is LinearDependencyResult => r !== null))\n }\n\n // Process blocked by relations (the related issue blocks this issue)\n // inverseRelations with type 'blocks' mean the related issue blocks this issue\n if (direction === 'blocked_by' || direction === 'both') {\n const blockedByRelations = inverseRelations.nodes.filter(\n (r) => r.type === IssueRelationType.Blocks,\n )\n // Resolve all source issues in parallel, then build results\n // Filter out undefined issue before Promise.all (LinearFetch<Issue> | undefined)\n const sourceIssuePromises = blockedByRelations\n .map((r) => r.issue)\n .filter((p): p is NonNullable<typeof p> => p !== undefined)\n const sourceIssues = await Promise.all(sourceIssuePromises)\n const blockedByResults = await Promise.all(\n sourceIssues.map((issue) => buildDependencyResult(issue)),\n )\n blockedBy.push(...blockedByResults.filter((r): r is LinearDependencyResult => r !== null))\n }\n\n return { blocking, blockedBy }\n } catch (error) {\n if (error instanceof LinearServiceError) {\n throw error\n }\n handleLinearError(error, 'getLinearIssueDependencies')\n }\n}\n\n/**\n * Delete an issue relation by ID\n * @param relationId - UUID of the relation to delete\n * @throws LinearServiceError on deletion failure\n */\nexport async function deleteLinearIssueRelation(relationId: string): Promise<void> {\n try {\n logger.debug(`Deleting Linear issue relation: ${relationId}`)\n const client = createLinearClient()\n\n const payload = await client.deleteIssueRelation(relationId)\n\n if (!payload.success) {\n throw new LinearServiceError('CLI_ERROR', 'Failed to delete Linear issue relation')\n }\n } catch (error) {\n if (error instanceof LinearServiceError) {\n throw error\n }\n handleLinearError(error, 'deleteLinearIssueRelation')\n }\n}\n\n// Issue List Operations (for il issues command)\n\nexport interface LinearIssueListItem {\n id: string\n title: string\n updatedAt: string\n url: string\n state: string\n}\n\n/**\n * Fetch a list of active Linear issues for a team, sorted by recently updated\n * @param teamKey - Team key (e.g., \"ENG\", \"PLAT\")\n * @param options - Fetch options\n * @param options.limit - Maximum number of issues to return (default: 100)\n * @param options.apiToken - Optional API token (takes precedence over env var)\n * @returns Array of issues\n * @throws LinearServiceError on fetch failure\n */\nexport async function fetchLinearIssueList(\n teamKey: string,\n options?: { limit?: number; apiToken?: string; mine?: boolean },\n): Promise<LinearIssueListItem[]> {\n try {\n const limit = options?.limit ?? 100\n\n logger.debug(`Fetching Linear issue list for team ${teamKey}`, { limit, mine: options?.mine })\n const client = createLinearClient(options?.apiToken)\n\n // Get team by key\n const teams = await client.teams()\n const team = teams.nodes.find((t) => t.key === teamKey)\n\n if (!team) {\n throw new LinearServiceError('NOT_FOUND', `Linear team ${teamKey} not found`)\n }\n\n // Build filter: always exclude completed/canceled states\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Linear SDK filter types are complex and not fully exported\n const filter: any = {\n state: {\n type: {\n nin: ['completed', 'canceled'],\n },\n },\n }\n\n // When --mine is set, filter to issues assigned to the authenticated user\n if (options?.mine) {\n filter.assignee = { isMe: { eq: true } }\n }\n\n // Fetch issues: filter out completed and canceled states, order by updatedAt\n const issues = await team.issues({\n first: limit,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any -- PaginationOrderBy is a const enum incompatible with isolatedModules\n orderBy: 'updatedAt' as any,\n filter,\n })\n\n // Build results, resolving state names in parallel\n const results = await Promise.all(\n issues.nodes.map(async (issue) => {\n const stateObj = await issue.state\n const state = stateObj?.name ?? 'unknown'\n\n return {\n id: issue.identifier,\n title: issue.title,\n updatedAt: issue.updatedAt.toISOString(),\n url: issue.url,\n state,\n }\n }),\n )\n\n return results\n } catch (error) {\n if (error instanceof LinearServiceError) {\n throw error\n }\n handleLinearError(error, 'fetchLinearIssueList')\n }\n}\n\n/**\n * Find the relation ID between two issues for removal\n * @param blockingIdentifier - Identifier of the blocking issue\n * @param blockedIdentifier - Identifier of the blocked issue\n * @returns The relation ID if found, null otherwise\n * @throws LinearServiceError on fetch failure\n */\nexport async function findLinearIssueRelation(\n blockingIdentifier: string,\n blockedIdentifier: string,\n): Promise<string | null> {\n try {\n logger.debug(`Finding Linear issue relation: ${blockingIdentifier} blocks ${blockedIdentifier}`)\n const client = createLinearClient()\n\n // Get the blocking issue\n const blockingIssue = await client.issue(blockingIdentifier)\n if (!blockingIssue) {\n throw new LinearServiceError('NOT_FOUND', `Linear issue ${blockingIdentifier} not found`)\n }\n\n // Get the blocked issue to get its ID\n const blockedIssue = await client.issue(blockedIdentifier)\n if (!blockedIssue) {\n throw new LinearServiceError('NOT_FOUND', `Linear issue ${blockedIdentifier} not found`)\n }\n\n // Find the relation from blockingIssue that blocks blockedIssue\n const relations = await blockingIssue.relations()\n\n // Filter to only 'blocks' relations and fetch related issues in parallel\n const blockingRelations = relations.nodes.filter(\n (r) => r.type === IssueRelationType.Blocks,\n )\n\n const relationsWithIssues = await Promise.all(\n blockingRelations.map(async (relation) => ({\n relation,\n relatedIssue: await relation.relatedIssue,\n })),\n )\n\n const matchingRelation = relationsWithIssues.find(\n ({ relatedIssue }) => relatedIssue?.id === blockedIssue.id,\n )\n\n return matchingRelation?.relation.id ?? null\n } catch (error) {\n if (error instanceof LinearServiceError) {\n throw error\n }\n handleLinearError(error, 'findLinearIssueRelation')\n }\n}\n","/**\n * Linear API response types (from @linear/sdk)\n */\n\n/**\n * Linear issue response from SDK\n */\nexport interface LinearIssue {\n /** Linear internal UUID */\n id: string\n /** Issue identifier in TEAM-NUMBER format (e.g., ENG-123) */\n identifier: string\n /** Issue title */\n title: string\n /** Issue description (markdown) */\n description?: string\n /** Current workflow state name */\n state?: string\n /** Linear web URL */\n url: string\n /** Creation timestamp (ISO string) */\n createdAt: string\n /** Last update timestamp (ISO string) */\n updatedAt: string\n}\n\n/**\n * Linear comment response from SDK\n */\nexport interface LinearComment {\n /** Comment UUID */\n id: string\n /** Comment body (markdown) */\n body: string\n /** Creation timestamp (ISO string) */\n createdAt: string\n /** Last update timestamp (ISO string) */\n updatedAt: string\n /** Comment URL */\n url: string\n}\n\n/**\n * Linear error codes\n */\nexport type LinearErrorCode =\n | 'NOT_FOUND'\n | 'UNAUTHORIZED'\n | 'INVALID_STATE'\n | 'RATE_LIMITED'\n | 'CLI_NOT_FOUND'\n | 'CLI_ERROR'\n\n/**\n * Linear error details\n */\nexport interface LinearError {\n code: LinearErrorCode\n message: string\n details?: unknown\n}\n\n/**\n * Custom error class for Linear operations\n */\nexport class LinearServiceError extends Error {\n constructor(\n public code: LinearErrorCode,\n message: string,\n public details?: unknown,\n ) {\n super(message)\n this.name = 'LinearServiceError'\n // Maintain proper stack trace for where error was thrown (V8 only)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, LinearServiceError)\n }\n }\n}\n","// JiraApiClient - REST API wrapper for Jira operations\n// Handles authentication and common API request patterns\n\nimport https from 'node:https'\nimport { getLogger } from '../../../utils/logger-context.js'\nimport { markdownToAdf } from './AdfMarkdownConverter.js'\n\n/**\n * Jira API configuration\n */\nexport interface JiraConfig {\n\thost: string // e.g., \"https://yourcompany.atlassian.net\"\n\tusername: string // email address or username\n\tapiToken: string // API token from Atlassian account\n}\n\n/**\n * Jira issue response from API\n */\n/**\n * Jira issue link (relationship between issues)\n */\nexport interface JiraIssueLink {\n\tid: string\n\ttype: {\n\t\tid: string\n\t\tname: string\n\t\tinward: string\n\t\toutward: string\n\t}\n\tinwardIssue?: {\n\t\tid: string\n\t\tkey: string\n\t\tfields: {\n\t\t\tsummary: string\n\t\t\tstatus: { name: string }\n\t\t}\n\t}\n\toutwardIssue?: {\n\t\tid: string\n\t\tkey: string\n\t\tfields: {\n\t\t\tsummary: string\n\t\t\tstatus: { name: string }\n\t\t}\n\t}\n}\n\nexport interface JiraIssue {\n\tid: string\n\tkey: string\n\tfields: {\n\t\tsummary: string\n\t\tdescription: string | null | unknown // Can be string, ADF object, or null\n\t\tstatus: {\n\t\t\tname: string\n\t\t}\n\t\tissuetype: {\n\t\t\tname: string\n\t\t}\n\t\tproject: {\n\t\t\tkey: string\n\t\t\tname: string\n\t\t}\n\t\tassignee: {\n\t\t\tdisplayName: string\n\t\t\temailAddress: string\n\t\t\taccountId: string\n\t\t} | null\n\t\treporter: {\n\t\t\tdisplayName: string\n\t\t\temailAddress: string\n\t\t\taccountId: string\n\t\t}\n\t\tlabels: string[]\n\t\tcreated: string\n\t\tupdated: string\n\t\tissuelinks?: JiraIssueLink[]\n\t\tparent?: {\n\t\t\tid: string\n\t\t\tkey: string\n\t\t\tfields: {\n\t\t\t\tsummary: string\n\t\t\t\tstatus: { name: string }\n\t\t\t}\n\t\t}\n\t\t[key: string]: unknown // Allow additional fields\n\t}\n\t[key: string]: unknown // Allow additional top-level fields\n}\n\n/**\n * Jira comment response from API\n */\nexport interface JiraComment {\n\tid: string\n\tauthor: {\n\t\tdisplayName: string\n\t\temailAddress: string\n\t\taccountId: string\n\t}\n\tbody: string | unknown // Can be string or ADF object\n\tcreated: string\n\tupdated: string\n\t[key: string]: unknown\n}\n\n/**\n * Jira transition response from API\n */\nexport interface JiraTransition {\n\tid: string\n\tname: string\n\tto: {\n\t\tid: string\n\t\tname: string\n\t}\n}\n\n/**\n * JiraApiClient provides low-level REST API access to Jira\n * \n * Authentication: Basic Auth with username and API token\n * API Reference: https://developer.atlassian.com/cloud/jira/platform/rest/v3/\n */\nexport class JiraApiClient {\n\tprivate readonly baseUrl: string\n\tprivate readonly authHeader: string\n\n\tconstructor(config: JiraConfig) {\n\t\tthis.baseUrl = `${config.host.replace(/\\/$/, '')}/rest/api/3`\n\t\t\n\t\t// Create Basic Auth header\n\t\tconst credentials = Buffer.from(`${config.username}:${config.apiToken}`).toString('base64')\n\t\tthis.authHeader = `Basic ${credentials}`\n\t}\n\n\t/**\n\t * Make an HTTP request to Jira API\n\t */\n\tprivate async request<T>(\n\t\tmethod: 'GET' | 'POST' | 'PUT' | 'DELETE',\n\t\tendpoint: string,\n\t\tbody?: unknown\n\t): Promise<T> {\n\t\tconst url = new URL(`${this.baseUrl}${endpoint}`)\n\t\tgetLogger().debug(`Jira API ${method} request`, { url: url.toString() })\n\t\tif (body) {\n\t\t\tgetLogger().debug('Jira API request body', JSON.stringify(body, null, 2))\n\t\t}\n\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst options: https.RequestOptions = {\n\t\t\t\thostname: url.hostname,\n\t\t\t\tport: url.port || 443,\n\t\t\t\tpath: url.pathname + url.search,\n\t\t\t\tmethod,\n\t\t\t\theaders: {\n\t\t\t\t\t'Authorization': this.authHeader,\n\t\t\t\t\t'Accept': 'application/json',\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t},\n\t\t\t}\n\n\t\t\tconst req = https.request({ ...options, timeout: 30000 }, (res) => {\n\t\t\t\tconst chunks: Buffer[] = []\n\n\t\t\t\tres.on('data', (chunk: Buffer) => {\n\t\t\t\t\tchunks.push(chunk)\n\t\t\t\t})\n\n\t\t\t\tres.on('end', () => {\n\t\t\t\t\tconst data = Buffer.concat(chunks).toString('utf8')\n\n\t\t\t\t\tif (!res.statusCode || res.statusCode < 200 || res.statusCode >= 300) {\n\t\t\t\t\t\tlet errorDetail = data\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst parsed = JSON.parse(data)\n\t\t\t\t\t\t\tconst parts: string[] = []\n\t\t\t\t\t\t\tif (parsed.errorMessages?.length) {\n\t\t\t\t\t\t\t\tparts.push(`messages: ${parsed.errorMessages.join(', ')}`)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (parsed.errors && Object.keys(parsed.errors).length) {\n\t\t\t\t\t\t\t\tparts.push(`field errors: ${JSON.stringify(parsed.errors)}`)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif (parts.length) {\n\t\t\t\t\t\t\t\terrorDetail = parts.join('; ')\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\t// Use raw data if not JSON\n\t\t\t\t\t\t}\n\t\t\t\t\t\treject(new Error(`Jira API error (${res.statusCode}): ${errorDetail}`))\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\t// Handle empty response (e.g., 204 No Content)\n\t\t\t\t\tif (res.statusCode === 204 || !data) {\n\t\t\t\t\t\tresolve({} as T)\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresolve(JSON.parse(data) as T)\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\treject(new Error(`Failed to parse Jira API response: ${error}`))\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\n\t\t\treq.on('timeout', () => {\n\t\t\t\treq.destroy()\n\t\t\t\treject(new Error('Jira API request timed out after 30 seconds'))\n\t\t\t})\n\n\t\t\treq.on('error', (error) => {\n\t\t\t\treject(new Error(`Jira API request failed: ${error.message}`))\n\t\t\t})\n\n\t\t\tif (body) {\n\t\t\t\treq.write(JSON.stringify(body))\n\t\t\t}\n\n\t\t\treq.end()\n\t\t})\n\t}\n\n\t/**\n\t * Make a GET request to Jira API\n\t */\n\tprivate async get<T>(endpoint: string): Promise<T> {\n\t\treturn this.request<T>('GET', endpoint)\n\t}\n\n\t/**\n\t * Make a POST request to Jira API\n\t */\n\tprivate async post<T>(endpoint: string, body: unknown): Promise<T> {\n\t\treturn this.request<T>('POST', endpoint, body)\n\t}\n\n\t/**\n\t * Make a PUT request to Jira API\n\t */\n\tprivate async put<T>(endpoint: string, body: unknown): Promise<T> {\n\t\treturn this.request<T>('PUT', endpoint, body)\n\t}\n\n\t/**\n\t * Make a DELETE request to Jira API\n\t */\n\tprivate async delete(endpoint: string): Promise<void> {\n\t\tawait this.request('DELETE', endpoint)\n\t}\n\n\t/**\n\t * Fetch an issue by key (e.g., \"PROJ-123\")\n\t */\n\tasync getIssue(issueKey: string): Promise<JiraIssue> {\n\t\treturn this.get<JiraIssue>(`/issue/${issueKey}`)\n\t}\n\n\t/**\n\t * Add a comment to an issue\n\t * Accepts Markdown content which is converted to ADF for Jira\n\t */\n\tasync addComment(issueKey: string, body: string): Promise<JiraComment> {\n\t\tconst adfBody = markdownToAdf(body);\n\t\tgetLogger().debug('Adding comment to Jira issue', { issueKey, bodyLength: body.length })\n\t\treturn this.post<JiraComment>(`/issue/${issueKey}/comment`, {\n\t\t\tbody: adfBody\n\t\t})\n\t}\n\n\t/**\n\t * Get all comments for an issue\n\t */\n\tasync getComments(issueKey: string): Promise<JiraComment[]> {\n\t\tconst response = await this.get<{ comments: JiraComment[]; total: number; maxResults: number }>(`/issue/${issueKey}/comment?maxResults=5000`)\n\t\tif (response.total > response.comments.length) {\n\t\t\tgetLogger().warn(`Comments truncated for issue ${issueKey}: returned ${response.comments.length} of ${response.total} total comments`)\n\t\t}\n\t\treturn response.comments\n\t}\n\n\t/**\n\t * Update a comment on an issue\n\t * Accepts Markdown content which is converted to ADF for Jira\n\t */\n\tasync updateComment(issueKey: string, commentId: string, body: string): Promise<JiraComment> {\n\t\treturn this.put<JiraComment>(`/issue/${issueKey}/comment/${commentId}`, {\n\t\t\tbody: markdownToAdf(body),\n\t\t})\n\t}\n\n\t/**\n\t * Get available transitions for an issue\n\t */\n\tasync getTransitions(issueKey: string): Promise<JiraTransition[]> {\n\t\tconst response = await this.get<{ transitions: JiraTransition[] }>(`/issue/${issueKey}/transitions`)\n\t\treturn response.transitions\n\t}\n\n\t/**\n\t * Transition an issue to a new state\n\t */\n\tasync transitionIssue(issueKey: string, transitionId: string): Promise<void> {\n\t\tawait this.post(`/issue/${issueKey}/transitions`, {\n\t\t\ttransition: {\n\t\t\t\tid: transitionId,\n\t\t\t},\n\t\t})\n\t}\n\n\t/**\n\t * Create a new issue\n\t * Accepts Markdown description which is converted to ADF for Jira\n\t */\n\tasync createIssue(projectKey: string, summary: string, description: string, issueType = 'Task'): Promise<JiraIssue> {\n\t\treturn this.post<JiraIssue>('/issue', {\n\t\t\tfields: {\n\t\t\t\tproject: {\n\t\t\t\t\tkey: projectKey,\n\t\t\t\t},\n\t\t\t\tsummary,\n\t\t\t\tdescription: markdownToAdf(description),\n\t\t\t\tissuetype: {\n\t\t\t\t\tname: issueType,\n\t\t\t\t},\n\t\t\t},\n\t\t})\n\t}\n\n\t/**\n\t * Update an issue's fields (summary, description)\n\t * @param issueKey - Jira issue key (e.g., \"PROJ-123\")\n\t * @param fields - Fields to update\n\t */\n\tasync updateIssue(issueKey: string, fields: { summary?: string; description?: string }): Promise<void> {\n\t\tconst updateFields: Record<string, unknown> = {}\n\t\tif (fields.summary !== undefined) {\n\t\t\tupdateFields.summary = fields.summary\n\t\t}\n\t\tif (fields.description !== undefined) {\n\t\t\tupdateFields.description = markdownToAdf(fields.description)\n\t\t}\n\n\t\tawait this.put(`/issue/${issueKey}`, { fields: updateFields })\n\t}\n\n\t/**\n\t * Create an issue with a parent (subtask or child issue)\n\t * Accepts Markdown description which is converted to ADF for Jira\n\t */\n\tasync createIssueWithParent(\n\t\tprojectKey: string,\n\t\tsummary: string,\n\t\tdescription: string,\n\t\tparentKey: string,\n\t\tissueType = 'Subtask'\n\t): Promise<JiraIssue> {\n\t\treturn this.post<JiraIssue>('/issue', {\n\t\t\tfields: {\n\t\t\t\tproject: {\n\t\t\t\t\tkey: projectKey,\n\t\t\t\t},\n\t\t\t\tsummary,\n\t\t\t\tdescription: markdownToAdf(description),\n\t\t\t\tissuetype: {\n\t\t\t\t\tname: issueType,\n\t\t\t\t},\n\t\t\t\tparent: {\n\t\t\t\t\tkey: parentKey,\n\t\t\t\t},\n\t\t\t},\n\t\t})\n\t}\n\n\t/**\n\t * Create an issue link (dependency/relationship between issues)\n\t * @param inwardKey - The issue key for the inward side (e.g., the blocked issue)\n\t * @param outwardKey - The issue key for the outward side (e.g., the blocking issue)\n\t * @param linkType - The link type name (e.g., \"Blocks\")\n\t */\n\tasync createIssueLink(inwardKey: string, outwardKey: string, linkType: string): Promise<void> {\n\t\tawait this.post('/issueLink', {\n\t\t\ttype: {\n\t\t\t\tname: linkType,\n\t\t\t},\n\t\t\tinwardIssue: {\n\t\t\t\tkey: inwardKey,\n\t\t\t},\n\t\t\toutwardIssue: {\n\t\t\t\tkey: outwardKey,\n\t\t\t},\n\t\t})\n\t}\n\n\t/**\n\t * Delete an issue link by ID\n\t */\n\tasync deleteIssueLink(linkId: string): Promise<void> {\n\t\tawait this.delete(`/issueLink/${linkId}`)\n\t}\n\n\t/**\n\t * Search issues using JQL\n\t * Automatically paginates through all results up to MAX_SEARCH_RESULTS.\n\t */\n\tasync searchIssues(jql: string): Promise<JiraIssue[]> {\n\t\tconst MAX_SEARCH_RESULTS = 5000\n\t\tconst allIssues: JiraIssue[] = []\n\t\tlet nextPageToken: string | undefined\n\t\tconst maxResults = 100\n\n\t\twhile (allIssues.length < MAX_SEARCH_RESULTS) {\n\t\t\tconst body: Record<string, unknown> = {\n\t\t\t\tjql,\n\t\t\t\tmaxResults,\n\t\t\t\tfields: [\n\t\t\t\t\t'summary', 'description', 'status', 'issuetype', 'project',\n\t\t\t\t\t'assignee', 'reporter', 'labels', 'created', 'updated',\n\t\t\t\t\t'issuelinks', 'parent',\n\t\t\t\t],\n\t\t\t}\n\t\t\tif (nextPageToken) {\n\t\t\t\tbody.nextPageToken = nextPageToken\n\t\t\t}\n\t\t\tconst response = await this.post<{ issues: JiraIssue[]; nextPageToken?: string }>(\n\t\t\t\t'/search/jql',\n\t\t\t\tbody\n\t\t\t)\n\t\t\tallIssues.push(...response.issues)\n\n\t\t\tif (!response.nextPageToken || response.issues.length === 0) {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tnextPageToken = response.nextPageToken\n\t\t}\n\n\t\tif (allIssues.length >= MAX_SEARCH_RESULTS) {\n\t\t\tgetLogger().warn(`Search results truncated at ${MAX_SEARCH_RESULTS} issues. The query matched more results than the safety cap allows.`, { jql, returnedCount: allIssues.length })\n\t\t}\n\n\t\treturn allIssues\n\t}\n\n\t/**\n\t * Test connection to Jira API\n\t */\n\tasync testConnection(): Promise<boolean> {\n\t\ttry {\n\t\t\tawait this.get('/myself')\n\t\t\treturn true\n\t\t} catch (error) {\n\t\t\tconst message = error instanceof Error ? error.message : String(error)\n\t\t\tif (message.includes('Jira API error (401)') || message.includes('Jira API error (403)')) {\n\t\t\t\tgetLogger().error('Jira connection test failed: authentication error', { error })\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n}\n","// AdfMarkdownConverter - Converts between Atlassian Document Format (ADF) and Markdown\n// Uses extended-markdown-adf-parser for bidirectional conversion\n\nimport { ADFDocument, Parser } from 'extended-markdown-adf-parser'\n\nconst parser = new Parser()\n\n/**\n * Represents a node in the ADF tree structure\n */\ninterface AdfNode {\n\ttype: string\n\tcontent?: AdfNode[]\n\tmarks?: Array<{ type: string; attrs?: Record<string, unknown> }>\n\ttext?: string\n\tattrs?: Record<string, unknown>\n}\n\n/**\n * Recursively traverse ADF tree and ensure code-marked text only has the code mark.\n * ADF specification requires that code marks are standalone - no other marks allowed.\n */\nfunction sanitizeCodeMarks(node: AdfNode): AdfNode {\n\t// If node has marks and one of them is 'code', keep only the code mark\n\tif (node.marks?.some((mark) => mark.type === 'code')) {\n\t\tnode.marks = [{ type: 'code' }]\n\t}\n\n\t// Recursively process child nodes\n\tif (node.content && Array.isArray(node.content)) {\n\t\tnode.content = node.content.map((child) => sanitizeCodeMarks(child))\n\t}\n\n\treturn node\n}\n\n/**\n * Block-level ADF node types that can appear directly inside table cells.\n * Any node type NOT in this set is considered inline and must be wrapped in a paragraph.\n */\nconst BLOCK_LEVEL_TYPES = new Set([\n\t'paragraph',\n\t'bulletList',\n\t'orderedList',\n\t'codeBlock',\n\t'heading',\n\t'blockquote',\n\t'rule',\n\t'mediaGroup',\n\t'nestedExpand',\n\t'panel',\n\t'table',\n\t'taskList',\n\t'decisionList',\n\t'mediaSingle',\n])\n\n/**\n * Recursively traverse ADF tree and ensure tableCell/tableHeader content\n * is wrapped in block-level nodes. Jira's ADF spec requires that table cells\n * only contain block-level nodes (like paragraph), not inline nodes (like text).\n */\nfunction wrapTableCellContent(node: AdfNode): AdfNode {\n\t// Recursively process child nodes first\n\tif (node.content && Array.isArray(node.content)) {\n\t\tnode.content = node.content.map((child) => wrapTableCellContent(child))\n\t}\n\n\t// Only process tableCell and tableHeader nodes\n\tif (node.type !== 'tableCell' && node.type !== 'tableHeader') {\n\t\treturn node\n\t}\n\n\tif (!node.content || node.content.length === 0) {\n\t\treturn node\n\t}\n\n\tconst allInline = node.content.every((child) => !BLOCK_LEVEL_TYPES.has(child.type))\n\n\tif (allInline) {\n\t\t// All children are inline - wrap them all in a single paragraph\n\t\tnode.content = [{ type: 'paragraph', content: node.content }]\n\t} else {\n\t\t// Mixed block and inline nodes - wrap consecutive inline runs in paragraphs\n\t\tconst newContent: AdfNode[] = []\n\t\tlet inlineRun: AdfNode[] = []\n\n\t\tfor (const child of node.content) {\n\t\t\tif (BLOCK_LEVEL_TYPES.has(child.type)) {\n\t\t\t\t// Flush any accumulated inline nodes as a paragraph\n\t\t\t\tif (inlineRun.length > 0) {\n\t\t\t\t\tnewContent.push({ type: 'paragraph', content: inlineRun })\n\t\t\t\t\tinlineRun = []\n\t\t\t\t}\n\t\t\t\tnewContent.push(child)\n\t\t\t} else {\n\t\t\t\tinlineRun.push(child)\n\t\t\t}\n\t\t}\n\n\t\t// Flush remaining inline nodes\n\t\tif (inlineRun.length > 0) {\n\t\t\tnewContent.push({ type: 'paragraph', content: inlineRun })\n\t\t}\n\n\t\tnode.content = newContent\n\t}\n\n\treturn node\n}\n\n/**\n * Counter for generating unique task item local IDs\n */\nlet taskIdCounter = 0\n\n/**\n * Represents a contiguous block of checkbox bullet items extracted from markdown.\n */\ninterface CheckboxBlock {\n\tstates: Array<'DONE' | 'TODO'>\n\ttexts: string[]\n}\n\n/**\n * Get the canonical plain text for a markdown string by parsing it through\n * the same ADF parser used for the full document. This ensures consistent\n * text matching regardless of markdown formatting quirks (e.g., literal\n * asterisks being misinterpreted as italic markers).\n */\nfunction getCanonicalPlainText(text: string): string {\n\tconst miniAdf = parser.markdownToAdf(text)\n\treturn getPlainText(miniAdf as AdfNode)\n}\n\n/**\n * Parse the original markdown to find contiguous blocks of bullet items where\n * ALL items use `- [x] ` or `- [ ] ` syntax (also supports `*` and `+` markers).\n * Returns the blocks in document order. The text field stores the canonical plain\n * text (obtained by mini-parsing through the ADF parser) for matching against ADF content.\n *\n * Only groups items at the same indentation level into a block. When indent changes,\n * the current block is broken to avoid mismatching nested checkbox lists.\n */\nfunction extractCheckboxBlocks(markdown: string): CheckboxBlock[] {\n\tconst lines = markdown.split('\\n')\n\tconst blocks: CheckboxBlock[] = []\n\n\tlet i = 0\n\twhile (i < lines.length) {\n\t\t// Collect contiguous bullet lines (checkbox or regular) at the same indent level\n\t\t// Store raw text first, then compute canonical text after collecting continuations\n\t\tconst bulletLines: Array<{ isCheckbox: boolean; state: 'DONE' | 'TODO' | null; rawText: string }> = []\n\t\tlet blockIndent: number | null = null\n\n\t\twhile (i < lines.length) {\n\t\t\tconst line = lines[i] ?? ''\n\t\t\tconst checkboxMatch = line.match(/^(\\s*)[-*+] \\[([ xX])\\] (.*)$/)\n\t\t\tif (checkboxMatch) {\n\t\t\t\tconst indent = checkboxMatch[1]?.length ?? 0\n\t\t\t\tif (blockIndent === null) {\n\t\t\t\t\tblockIndent = indent\n\t\t\t\t} else if (indent !== blockIndent) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tconst state = checkboxMatch[2] === ' ' ? 'TODO' : 'DONE'\n\t\t\t\tbulletLines.push({ isCheckbox: true, state, rawText: checkboxMatch[3] ?? '' })\n\t\t\t\ti++\n\t\t\t} else if (line.match(/^\\s*[-*+] /)) {\n\t\t\t\t// Regular bullet item (no checkbox) - check indent\n\t\t\t\tconst indentMatch = line.match(/^(\\s*)/)\n\t\t\t\tconst indent = indentMatch?.[1]?.length ?? 0\n\t\t\t\tif (blockIndent === null) {\n\t\t\t\t\tblockIndent = indent\n\t\t\t\t} else if (indent !== blockIndent) {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tbulletLines.push({ isCheckbox: false, state: null, rawText: '' })\n\t\t\t\ti++\n\t\t\t} else if (bulletLines.length > 0 && line.match(/^\\s/) && line.trim() !== '') {\n\t\t\t\t// Continuation line of the previous list item (indented, non-empty)\n\t\t\t\t// Append to the last bullet item's raw text\n\t\t\t\tconst lastItem = bulletLines[bulletLines.length - 1]\n\t\t\t\tif (lastItem) {\n\t\t\t\t\tlastItem.rawText += '\\n' + line.trim()\n\t\t\t\t}\n\t\t\t\ti++\n\t\t\t} else {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif (bulletLines.length > 0) {\n\t\t\tconst allCheckboxes = bulletLines.every((l) => l.isCheckbox)\n\t\t\tif (allCheckboxes) {\n\t\t\t\tblocks.push({\n\t\t\t\t\tstates: bulletLines.map((l) => l.state as 'DONE' | 'TODO'),\n\t\t\t\t\ttexts: bulletLines.map((l) => getCanonicalPlainText(l.rawText)),\n\t\t\t\t})\n\t\t\t}\n\t\t} else {\n\t\t\ti++\n\t\t}\n\t}\n\n\treturn blocks\n}\n\n/**\n * Recursively extract all plain text from an ADF node,\n * handling formatted content (bold, italic, code, links).\n */\nfunction getPlainText(node: AdfNode): string {\n\tif (node.type === 'text' && node.text !== undefined) return node.text\n\tif (!node.content) return ''\n\treturn node.content.map(getPlainText).join('')\n}\n\n/**\n * Recursively traverse ADF tree and convert bulletList nodes that match\n * extracted checkbox blocks into taskList/taskItem nodes.\n *\n * Uses a cursor into the blocks array to match bulletLists in document order.\n * The cursor is shared across the entire tree traversal.\n */\nfunction convertCheckboxesToTaskList(node: AdfNode, blocks: CheckboxBlock[]): AdfNode {\n\tconst cursor = { index: 0 }\n\treturn convertCheckboxesRecursive(node, blocks, cursor)\n}\n\nfunction convertCheckboxesRecursive(\n\tnode: AdfNode,\n\tblocks: CheckboxBlock[],\n\tcursor: { index: number }\n): AdfNode {\n\tif (node.type === 'bulletList' && node.content && node.content.length > 0 && cursor.index < blocks.length) {\n\t\tconst block = blocks[cursor.index]\n\t\tif (!block) return node\n\n\t\t// Check if this bulletList matches the next checkbox block\n\t\tif (node.content.length === block.states.length) {\n\t\t\tconst plaintexts = node.content.map((listItem) => getPlainText(listItem))\n\t\t\tconst matches = plaintexts.every((text, i) => text === block.texts[i])\n\n\t\t\tif (matches) {\n\t\t\t\t// Guard: all listItems must have simple structure (single paragraph child)\n\t\t\t\t// Multi-paragraph or complex items cannot be safely converted to taskItem\n\t\t\t\tconst allSimple = node.content.every((item) => {\n\t\t\t\t\treturn item.content?.length === 1 && item.content[0]?.type === 'paragraph'\n\t\t\t\t})\n\t\t\t\tif (!allSimple) {\n\t\t\t\t\tcursor.index++ // Consume the block even though we can't convert it\n\t\t\t\t\treturn node // Items too complex for taskItem\n\t\t\t\t}\n\n\t\t\t\t// Convert bulletList -> taskList\n\t\t\t\tcursor.index++\n\t\t\t\tnode.type = 'taskList'\n\t\t\t\tnode.attrs = { localId: `tasklist-${++taskIdCounter}` }\n\n\t\t\t\tfor (const [i, listItem] of node.content.entries()) {\n\t\t\t\t\tlistItem.type = 'taskItem'\n\t\t\t\t\tlistItem.attrs = {\n\t\t\t\t\t\tlocalId: `task-${++taskIdCounter}`,\n\t\t\t\t\t\tstate: block.states[i],\n\t\t\t\t\t}\n\n\t\t\t\t\t// Unwrap paragraph: listItem has paragraph > [inline nodes],\n\t\t\t\t\t// but taskItem should have inline nodes directly\n\t\t\t\t\tconst firstChild = listItem.content?.[0]\n\t\t\t\t\tif (firstChild?.type === 'paragraph' && firstChild.content) {\n\t\t\t\t\t\tlistItem.content = firstChild.content\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn node\n\t\t\t}\n\t\t}\n\t}\n\n\t// Recursively process child nodes\n\tif (node.content && Array.isArray(node.content)) {\n\t\tnode.content = node.content.map((child) => convertCheckboxesRecursive(child, blocks, cursor))\n\t}\n\n\treturn node\n}\n\n/**\n * Convert HTML details/summary blocks to ADF expand fence syntax\n * The extended-markdown-adf-parser library supports ~~~expand title=\"...\"~~~ syntax\n * but not HTML <details><summary> tags\n *\n * @param markdown - Markdown string potentially containing HTML details/summary blocks\n * @returns Markdown with details/summary converted to ADF expand fence syntax\n */\nexport function convertDetailsToExpandSyntax(markdown: string): string {\n\tif (!markdown) return markdown\n\n\t// Process from innermost to outermost to handle nesting correctly\n\tlet previousText = ''\n\tlet currentText = markdown\n\n\twhile (previousText !== currentText) {\n\t\tpreviousText = currentText\n\t\t// Match <details> blocks with optional attributes on the tags\n\t\tcurrentText = currentText.replace(\n\t\t\t/<details[^>]*>\\s*<summary[^>]*>([\\s\\S]*?)<\\/summary>([\\s\\S]*?)<\\/details>/gi,\n\t\t\t(_match, summary, content) => {\n\t\t\t\t// Clean up the summary - trim whitespace and decode HTML entities\n\t\t\t\tconst cleanSummary = summary\n\t\t\t\t\t.trim()\n\t\t\t\t\t.replace(/</g, '<')\n\t\t\t\t\t.replace(/>/g, '>')\n\t\t\t\t\t.replace(/&/g, '&')\n\t\t\t\t\t.replace(/"/g, '\"')\n\t\t\t\t\t.replace(/'/g, \"'\")\n\n\t\t\t\t// Clean up the content - trim and normalize excessive blank lines\n\t\t\t\tlet cleanContent = content.trim()\n\t\t\t\tcleanContent = cleanContent.replace(/\\n{3,}/g, '\\n\\n')\n\n\t\t\t\t// Build ADF expand fence syntax\n\t\t\t\tif (cleanContent) {\n\t\t\t\t\treturn `~~~expand title=\"${cleanSummary}\"\\n${cleanContent}\\n~~~`\n\t\t\t\t} else {\n\t\t\t\t\treturn `~~~expand title=\"${cleanSummary}\"\\n~~~`\n\t\t\t\t}\n\t\t\t}\n\t\t)\n\t}\n\n\treturn currentText\n}\n\n/**\n * Convert ADF (Atlassian Document Format) to Markdown\n * Used when reading issue descriptions and comments from Jira\n *\n * @param adf - ADF object, string, null, or undefined\n * @returns Markdown string\n */\nexport function adfToMarkdown(adf: unknown): string {\n\t// Handle null/undefined\n\tif (!adf) return ''\n\n\t// Handle plain string (already text, not ADF)\n\tif (typeof adf === 'string') return adf\n\n\t// Convert ADF object to markdown\n\treturn parser.adfToMarkdown(adf as ADFDocument)\n}\n\n/**\n * Convert Markdown to ADF (Atlassian Document Format)\n * Used when writing issue descriptions and comments to Jira\n *\n * @param markdown - Markdown string\n * @returns ADF object suitable for Jira API v3\n */\nexport function markdownToAdf(markdown: string): object {\n\tif (!markdown) {\n\t\treturn { type: 'doc', version: 1, content: [] }\n\t}\n\t// Reset task ID counter for deterministic output\n\ttaskIdCounter = 0\n\t// Extract checkbox info BEFORE conversion (library will strip [x]/[ ])\n\tconst checkboxBlocks = extractCheckboxBlocks(markdown)\n\t// Pre-process: convert details/summary to expand syntax\n\tconst preprocessed = convertDetailsToExpandSyntax(markdown)\n\tconst adf = parser.markdownToAdf(preprocessed)\n\t// Post-process the ADF tree\n\tlet result = sanitizeCodeMarks(adf as AdfNode)\n\tresult = wrapTableCellContent(result)\n\tresult = convertCheckboxesToTaskList(result, checkboxBlocks)\n\treturn result\n}\n","// JiraIssueTracker - Implements IssueTracker interface for Jira\n// Provides issue management operations via Jira REST API\n\nimport type { IssueTracker } from '../../IssueTracker.js'\nimport type { Issue, IssueTrackerInputDetection } from '../../../types/index.js'\nimport { JiraApiClient, type JiraConfig, type JiraIssue, type JiraTransition } from './JiraApiClient.js'\nimport { getLogger } from '../../../utils/logger-context.js'\nimport { promptConfirmation } from '../../../utils/prompt.js'\nimport { adfToMarkdown } from './AdfMarkdownConverter.js'\n\n/**\n * Jira-specific configuration\n */\nexport interface JiraTrackerConfig extends JiraConfig {\n\tprojectKey: string\n\ttransitionMappings?: Record<string, string> // Map iloom states to Jira transition names\n\tdefaultIssueType?: string // Default issue type for creating issues (e.g., \"Task\", \"Story\")\n\tdefaultSubtaskType?: string // Default issue type for creating subtasks (e.g., \"Subtask\", \"Sub-task\")\n}\n\n/**\n * JiraIssueTracker implements IssueTracker for Jira\n * \n * Key differences from GitHub/Linear:\n * - Issue identifiers are strings (e.g., \"PROJ-123\")\n * - No issue prefix (unlike GitHub's \"#\")\n * - State changes require workflow transitions (not direct status updates)\n * - Content uses Atlassian Document Format (ADF), converted to/from Markdown\n */\nexport class JiraIssueTracker implements IssueTracker {\n\treadonly providerName = 'jira'\n\treadonly supportsPullRequests = false\n\n\tprivate readonly client: JiraApiClient\n\tprivate readonly config: JiraTrackerConfig\n\tprivate prompter: (message: string) => Promise<boolean>\n\n\tconstructor(config: JiraTrackerConfig, options?: {\n\t\tprompter?: (message: string) => Promise<boolean>\n\t}) {\n\t\tthis.config = config\n\t\tthis.client = new JiraApiClient({\n\t\t\thost: config.host,\n\t\t\tusername: config.username,\n\t\t\tapiToken: config.apiToken,\n\t\t})\n\t\tthis.prompter = options?.prompter ?? promptConfirmation\n\t}\n\n\t/**\n\t * Normalize identifier to canonical uppercase form\n\t * Jira issue keys are case-sensitive in the API (must be uppercase)\n\t */\n\tnormalizeIdentifier(identifier: string | number): string {\n\t\treturn String(identifier).toUpperCase()\n\t}\n\n\t/**\n\t * Detect input type from user input\n\t * Jira issues follow pattern: PROJECTKEY-123 (case-insensitive)\n\t */\n\tasync detectInputType(input: string): Promise<IssueTrackerInputDetection> {\n\t\t// Pattern: PROJECTKEY-123 (case-insensitive to accept lowercase from branch names or user input)\n\t\tconst jiraPattern = /^([A-Z][A-Z0-9]+)-(\\d+)$/i\n\t\tconst match = input.match(jiraPattern)\n\n\t\tif (!match) {\n\t\t\treturn { type: 'unknown', identifier: null, rawInput: input }\n\t\t}\n\n\t\tconst issueKey = this.normalizeIdentifier(input)\n\t\tgetLogger().debug('Checking if input is a Jira issue', { issueKey })\n\n\t\t// Verify the issue exists\n\t\ttry {\n\t\t\tawait this.client.getIssue(issueKey)\n\t\t\treturn { type: 'issue', identifier: issueKey, rawInput: input }\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && (/404/.test(error.message) || /not found/i.test(error.message))) {\n\t\t\t\tgetLogger().debug('Issue not found', { issueKey, error })\n\t\t\t\treturn { type: 'unknown', identifier: null, rawInput: input }\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Fetch issue details\n\t */\n\tasync fetchIssue(identifier: string | number): Promise<Issue> {\n\t\tconst issueKey = this.normalizeIdentifier(identifier)\n\t\tgetLogger().debug('Fetching Jira issue', { issueKey })\n\n\t\tconst jiraIssue = await this.client.getIssue(issueKey)\n\t\treturn this.mapJiraIssueToIssue(jiraIssue)\n\t}\n\n\t/**\n\t * Check if issue exists (silent validation)\n\t */\n\tasync isValidIssue(identifier: string | number): Promise<Issue | false> {\n\t\ttry {\n\t\t\treturn await this.fetchIssue(identifier)\n\t\t} catch (error) {\n\t\t\tif (error instanceof Error && (/404/.test(error.message) || /not found/i.test(error.message))) {\n\t\t\t\tgetLogger().debug('Issue validation failed: not found', { identifier, error })\n\t\t\t\treturn false\n\t\t\t}\n\t\t\tthrow error\n\t\t}\n\t}\n\n\t/**\n\t * Validate issue state\n\t * Note: Jira doesn't have a simple \"closed\" state - depends on workflow\n\t */\n\tasync validateIssueState(issue: Issue): Promise<void> {\n\t\tgetLogger().debug('Jira issue state', { issueKey: issue.number, state: issue.state })\n\t\tif (issue.state === 'closed') {\n\t\t\tconst shouldContinue = await this.prompter(\n\t\t\t\t`Issue ${issue.number} is in a completed state. Continue anyway?`\n\t\t\t)\n\t\t\tif (!shouldContinue) {\n\t\t\t\tthrow new Error('User cancelled due to completed issue')\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Create a new issue\n\t */\n\tasync createIssue(\n\t\ttitle: string,\n\t\tbody: string,\n\t\t_repository?: string,\n\t\t_labels?: string[]\n\t): Promise<{ number: string | number; url: string }> {\n\t\tgetLogger().debug('Creating Jira issue', { title, projectKey: this.config.projectKey })\n\n\t\t// Convert markdown body to plain text for Jira description\n\t\t// Note: Jira API expects Atlassian Document Format (ADF)\n\t\t// We use a simplified plain text approach here\n\t\tconst jiraIssue = await this.client.createIssue(\n\t\t\tthis.config.projectKey,\n\t\t\ttitle,\n\t\t\tbody,\n\t\t\tthis.config.defaultIssueType\n\t\t)\n\n\t\treturn {\n\t\t\tnumber: jiraIssue.key,\n\t\t\turl: `${this.config.host}/browse/${jiraIssue.key}`,\n\t\t}\n\t}\n\n\t/**\n\t * Get issue URL\n\t */\n\tasync getIssueUrl(identifier: string | number): Promise<string> {\n\t\tconst issueKey = this.normalizeIdentifier(identifier)\n\t\treturn `${this.config.host}/browse/${issueKey}`\n\t}\n\n\t/**\n\t * Move issue to \"In Progress\" state\n\t * Uses configured transition mapping or default transition name\n\t */\n\tasync moveIssueToInProgress(identifier: string | number): Promise<void> {\n\t\tconst issueKey = this.normalizeIdentifier(identifier)\n\t\tgetLogger().debug('Moving Jira issue to In Progress', { issueKey })\n\n\t\t// Get available transitions\n\t\tconst transitions = await this.client.getTransitions(issueKey)\n\t\t\n\t\t// Look for the transition in config mapping or use default names\n\t\tconst transitionName = this.config.transitionMappings?.['In Progress'] \n\t\t\t?? this.findTransitionByName(transitions, ['In Progress', 'Start Progress', 'Start'])\n\n\t\tif (!transitionName) {\n\t\t\tthrow new Error(\n\t\t\t\t`Could not find \"In Progress\" transition for ${issueKey}. ` +\n\t\t\t\t`Available transitions: ${transitions.map(t => t.name).join(', ')}. ` +\n\t\t\t\t`Configure custom mapping in settings.json: issueManagement.jira.transitionMappings`\n\t\t\t)\n\t\t}\n\n\t\t// Find transition ID\n\t\tconst transition = transitions.find(t => t.name === transitionName)\n\t\tif (!transition) {\n\t\t\tthrow new Error(`Transition \"${transitionName}\" not found`)\n\t\t}\n\n\t\tawait this.client.transitionIssue(issueKey, transition.id)\n\t\tgetLogger().info('Issue transitioned successfully', { issueKey, transition: transitionName })\n\t}\n\n\t/**\n\t * Move issue to \"Ready for Review\" state\n\t * Uses configured transition mapping or default transition name\n\t */\n\tasync moveIssueToReadyForReview(identifier: string | number): Promise<void> {\n\t\tconst issueKey = this.normalizeIdentifier(identifier)\n\t\tgetLogger().debug('Moving Jira issue to Ready for Review', { issueKey })\n\n\t\t// Get available transitions\n\t\tconst transitions = await this.client.getTransitions(issueKey)\n\n\t\t// Look for the transition in config mapping or use default names\n\t\tconst transitionName = this.config.transitionMappings?.['Ready for Review']\n\t\t\t?? this.findTransitionByName(transitions, ['Ready for Review', 'In Review', 'Code Review', 'Review'])\n\n\t\tif (!transitionName) {\n\t\t\tthrow new Error(\n\t\t\t\t`Could not find \"Ready for Review\" transition for ${issueKey}. ` +\n\t\t\t\t`Available transitions: ${transitions.map(t => t.name).join(', ')}. ` +\n\t\t\t\t`Configure custom mapping in settings.json: issueManagement.jira.transitionMappings`\n\t\t\t)\n\t\t}\n\n\t\t// Find transition ID\n\t\tconst transition = transitions.find(t => t.name === transitionName)\n\t\tif (!transition) {\n\t\t\tthrow new Error(`Transition \"${transitionName}\" not found`)\n\t\t}\n\n\t\tawait this.client.transitionIssue(issueKey, transition.id)\n\t\tgetLogger().info('Issue transitioned to Ready for Review', { issueKey, transition: transitionName })\n\t}\n\n\t/**\n\t * Close an issue by transitioning to \"Done\" state\n\t * Uses configured transition mapping or default transition names\n\t */\n\tasync closeIssue(identifier: string | number): Promise<void> {\n\t\tconst issueKey = this.normalizeIdentifier(identifier)\n\t\tgetLogger().debug('Closing Jira issue', { issueKey })\n\n\t\t// Get available transitions\n\t\tconst transitions = await this.client.getTransitions(issueKey)\n\n\t\t// Look for the transition in config mapping or use default names\n\t\tconst transitionName = this.config.transitionMappings?.['Done']\n\t\t\t?? this.findTransitionByName(transitions, ['Done', 'Close', 'Closed', 'Resolve', 'Resolved'])\n\n\t\tif (!transitionName) {\n\t\t\tthrow new Error(\n\t\t\t\t`Could not find \"Done\" transition for ${issueKey}. ` +\n\t\t\t\t`Available transitions: ${transitions.map(t => t.name).join(', ')}. ` +\n\t\t\t\t`Configure custom mapping in settings.json: issueManagement.jira.transitionMappings`\n\t\t\t)\n\t\t}\n\n\t\t// Find transition ID\n\t\tconst transition = transitions.find(t => t.name === transitionName)\n\t\tif (!transition) {\n\t\t\tthrow new Error(`Transition \"${transitionName}\" not found`)\n\t\t}\n\n\t\tawait this.client.transitionIssue(issueKey, transition.id)\n\t\tgetLogger().info('Issue closed successfully', { issueKey, transition: transitionName })\n\t}\n\n\t/**\n\t * Reopen an issue by transitioning back to an open state\n\t * Uses configured transition mapping or default transition names\n\t */\n\tasync reopenIssue(identifier: string | number): Promise<void> {\n\t\tconst issueKey = this.normalizeIdentifier(identifier)\n\t\tgetLogger().debug('Reopening Jira issue', { issueKey })\n\n\t\t// Get available transitions\n\t\tconst transitions = await this.client.getTransitions(issueKey)\n\n\t\t// Look for the transition in config mapping or use default names\n\t\tconst transitionName = this.config.transitionMappings?.['Reopen']\n\t\t\t?? this.findTransitionByName(transitions, ['Reopen', 'To Do', 'Open', 'Backlog'])\n\n\t\tif (!transitionName) {\n\t\t\tthrow new Error(\n\t\t\t\t`Could not find \"Reopen\" transition for ${issueKey}. ` +\n\t\t\t\t`Available transitions: ${transitions.map(t => t.name).join(', ')}. ` +\n\t\t\t\t`Configure custom mapping in settings.json: issueManagement.jira.transitionMappings`\n\t\t\t)\n\t\t}\n\n\t\t// Find transition ID\n\t\tconst transition = transitions.find(t => t.name === transitionName)\n\t\tif (!transition) {\n\t\t\tthrow new Error(`Transition \"${transitionName}\" not found`)\n\t\t}\n\n\t\tawait this.client.transitionIssue(issueKey, transition.id)\n\t\tgetLogger().info('Issue reopened successfully', { issueKey, transition: transitionName })\n\t}\n\n\t/**\n\t * Extract context from issue for AI prompts\n\t */\n\textractContext(entity: Issue): string {\n\t\treturn `Issue: ${entity.number}\nTitle: ${entity.title}\nStatus: ${entity.state}\nURL: ${entity.url}\n\nDescription:\n${entity.body}\n\n${entity.labels.length > 0 ? `Labels: ${entity.labels.join(', ')}` : ''}\n${entity.assignees.length > 0 ? `Assignees: ${entity.assignees.join(', ')}` : ''}`\n\t}\n\n\t/**\n\t * Fetch child issues of a Jira parent issue using JQL\n\t * @param parentIdentifier - Jira issue key (e.g., \"PROJ-123\")\n\t * @param _repo - Repository (unused for Jira)\n\t * @returns Array of child issues\n\t */\n\tasync getChildIssues(parentIdentifier: string, _repo?: string): Promise<Array<{ id: string; title: string; url: string; state: string }>> {\n\t\tconst parentKey = this.normalizeIdentifier(parentIdentifier)\n\t\tconst jiraKeyPattern = /^[A-Z][A-Z0-9]+-\\d+$/\n\t\tif (!jiraKeyPattern.test(parentKey)) {\n\t\t\tgetLogger().warn(`Invalid Jira issue key format: ${parentKey}`)\n\t\t\treturn []\n\t\t}\n\t\tconst issues = await this.client.searchIssues(`parent = ${parentKey}`)\n\t\treturn issues.map(issue => ({\n\t\t\tid: issue.key,\n\t\t\ttitle: issue.fields.summary,\n\t\t\turl: `${this.config.host}/browse/${issue.key}`,\n\t\t\tstate: issue.fields.status.name.toLowerCase(),\n\t\t}))\n\t}\n\n\t/**\n\t * Get issue details (alias for fetchIssue for MCP compatibility)\n\t */\n\tasync getIssue(identifier: string | number): Promise<Issue> {\n\t\treturn this.fetchIssue(identifier)\n\t}\n\n\t/**\n\t * Get all comments for an issue\n\t */\n\tasync getComments(identifier: string | number): Promise<Array<{\n\t\tid: string\n\t\tbody: string\n\t\tauthor: { displayName: string; emailAddress: string; accountId: string }\n\t\tcreatedAt: string\n\t\tupdatedAt: string\n\t}>> {\n\t\tconst issueKey = this.normalizeIdentifier(identifier)\n\t\tgetLogger().debug('Fetching Jira comments', { issueKey })\n\n\t\tconst comments = await this.client.getComments(issueKey)\n\t\t\n\t\t// Map to expected format\n\t\treturn comments.map(comment => ({\n\t\t\tid: comment.id,\n\t\t\tbody: adfToMarkdown(comment.body),\n\t\t\tauthor: comment.author,\n\t\t\tcreatedAt: comment.created,\n\t\t\tupdatedAt: comment.updated,\n\t\t}))\n\t}\n\n\t/**\n\t * Add a comment to an issue\n\t */\n\tasync addComment(identifier: string | number, body: string): Promise<{ id: string }> {\n\t\tconst issueKey = this.normalizeIdentifier(identifier)\n\t\tgetLogger().debug('Adding Jira comment', { issueKey })\n\n\t\tconst comment = await this.client.addComment(issueKey, body)\n\t\treturn { id: comment.id }\n\t}\n\n\t/**\n\t * Update an existing comment\n\t */\n\tasync updateComment(identifier: string | number, commentId: string, body: string): Promise<void> {\n\t\tconst issueKey = this.normalizeIdentifier(identifier)\n\t\tgetLogger().debug('Updating Jira comment', { issueKey, commentId })\n\n\t\tawait this.client.updateComment(issueKey, commentId, body)\n\t}\n\n\t/**\n\t * Get the underlying API client (for direct API access by MCP provider)\n\t */\n\tgetApiClient(): JiraApiClient {\n\t\treturn this.client\n\t}\n\n\t/**\n\t * Get configuration (for MCP provider)\n\t */\n\tgetConfig(): JiraTrackerConfig {\n\t\treturn this.config\n\t}\n\n\t/**\n\t * Map Jira API issue to generic Issue type\n\t */\n\tprivate mapJiraIssueToIssue(jiraIssue: JiraIssue): Issue & {\n\t\tid?: string\n\t\tkey?: string\n\t\tauthor?: {\n\t\t\tdisplayName: string\n\t\t\temailAddress: string\n\t\t\taccountId: string\n\t\t}\n\t\tassignee?: {\n\t\t\tdisplayName: string\n\t\t\temailAddress: string\n\t\t\taccountId: string\n\t\t} | null\n\t\tissueType?: string\n\t\tstatus?: string\n\t} {\n\t\t// Extract description - handle ADF format or plain string\n\t\tconst description = adfToMarkdown(jiraIssue.fields.description)\n\n\t\treturn {\n\t\t\tid: jiraIssue.id,\n\t\t\tkey: jiraIssue.key,\n\t\t\tnumber: jiraIssue.key,\n\t\t\ttitle: jiraIssue.fields.summary,\n\t\t\tbody: description,\n\t\t\tstate: this.mapJiraStatusToState(jiraIssue.fields.status.name),\n\t\t\tlabels: jiraIssue.fields.labels,\n\t\t\tassignees: jiraIssue.fields.assignee \n\t\t\t\t? [jiraIssue.fields.assignee.displayName]\n\t\t\t\t: [],\n\t\t\tassignee: jiraIssue.fields.assignee,\n\t\t\tauthor: jiraIssue.fields.reporter,\n\t\t\turl: `${this.config.host}/browse/${jiraIssue.key}`,\n\t\t\tissueType: jiraIssue.fields.issuetype.name,\n\t\t\tstatus: jiraIssue.fields.status.name,\n\t\t}\n\t}\n\n\tprivate mapJiraStatusToState(statusName: string): 'open' | 'closed' {\n\t\tconst normalized = statusName.toLowerCase()\n\t\tconst closedStatuses = ['done', 'closed', 'resolved', 'cancelled', 'canceled']\n\t\treturn closedStatuses.includes(normalized) ? 'closed' : 'open'\n\t}\n\n\t/**\n\t * Find a transition by name, trying multiple possible names\n\t */\n\tprivate findTransitionByName(transitions: JiraTransition[], names: string[]): string | null {\n\t\tfor (const name of names) {\n\t\t\tconst transition = transitions.find(t => \n\t\t\t\tt.name.toLowerCase() === name.toLowerCase()\n\t\t\t)\n\t\t\tif (transition) {\n\t\t\t\treturn transition.name\n\t\t\t}\n\t\t}\n\t\treturn null\n\t}\n}\n"],"mappings":"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","names":["issue","_a"]}
|
|
@@ -15,7 +15,7 @@ var ClaudeBranchNameStrategy = class {
|
|
|
15
15
|
this.claudeModel = claudeModel;
|
|
16
16
|
}
|
|
17
17
|
async generate(issueNumber, title) {
|
|
18
|
-
const { generateBranchName } = await import("./claude-
|
|
18
|
+
const { generateBranchName } = await import("./claude-P3NQR6IJ.js");
|
|
19
19
|
return generateBranchName(title, issueNumber, this.claudeModel);
|
|
20
20
|
}
|
|
21
21
|
};
|
|
@@ -52,4 +52,4 @@ export {
|
|
|
52
52
|
ClaudeBranchNameStrategy,
|
|
53
53
|
DefaultBranchNamingService
|
|
54
54
|
};
|
|
55
|
-
//# sourceMappingURL=chunk-
|
|
55
|
+
//# sourceMappingURL=chunk-J5S7DFYC.js.map
|