gmc-openspec 1.0.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.
Files changed (333) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +207 -0
  3. package/bin/openspec.js +3 -0
  4. package/dist/cli/index.d.ts +2 -0
  5. package/dist/cli/index.js +494 -0
  6. package/dist/commands/change.d.ts +35 -0
  7. package/dist/commands/change.js +277 -0
  8. package/dist/commands/completion.d.ts +72 -0
  9. package/dist/commands/completion.js +264 -0
  10. package/dist/commands/config.d.ts +36 -0
  11. package/dist/commands/config.js +611 -0
  12. package/dist/commands/feedback.d.ts +9 -0
  13. package/dist/commands/feedback.js +183 -0
  14. package/dist/commands/jira.d.ts +3 -0
  15. package/dist/commands/jira.js +249 -0
  16. package/dist/commands/schema.d.ts +6 -0
  17. package/dist/commands/schema.js +869 -0
  18. package/dist/commands/show.d.ts +14 -0
  19. package/dist/commands/show.js +132 -0
  20. package/dist/commands/spec.d.ts +15 -0
  21. package/dist/commands/spec.js +225 -0
  22. package/dist/commands/validate.d.ts +24 -0
  23. package/dist/commands/validate.js +294 -0
  24. package/dist/commands/workflow/index.d.ts +17 -0
  25. package/dist/commands/workflow/index.js +12 -0
  26. package/dist/commands/workflow/instructions.d.ts +29 -0
  27. package/dist/commands/workflow/instructions.js +336 -0
  28. package/dist/commands/workflow/new-change.d.ts +13 -0
  29. package/dist/commands/workflow/new-change.js +92 -0
  30. package/dist/commands/workflow/schemas.d.ts +10 -0
  31. package/dist/commands/workflow/schemas.js +34 -0
  32. package/dist/commands/workflow/shared.d.ts +57 -0
  33. package/dist/commands/workflow/shared.js +116 -0
  34. package/dist/commands/workflow/status.d.ts +14 -0
  35. package/dist/commands/workflow/status.js +87 -0
  36. package/dist/commands/workflow/templates.d.ts +16 -0
  37. package/dist/commands/workflow/templates.js +69 -0
  38. package/dist/commands/workspace/open.d.ts +29 -0
  39. package/dist/commands/workspace/open.js +84 -0
  40. package/dist/commands/workspace/operations.d.ts +23 -0
  41. package/dist/commands/workspace/operations.js +475 -0
  42. package/dist/commands/workspace/selection.d.ts +6 -0
  43. package/dist/commands/workspace/selection.js +113 -0
  44. package/dist/commands/workspace/types.d.ts +88 -0
  45. package/dist/commands/workspace/types.js +36 -0
  46. package/dist/commands/workspace.d.ts +6 -0
  47. package/dist/commands/workspace.js +868 -0
  48. package/dist/core/archive.d.ts +11 -0
  49. package/dist/core/archive.js +318 -0
  50. package/dist/core/artifact-graph/graph.d.ts +56 -0
  51. package/dist/core/artifact-graph/graph.js +141 -0
  52. package/dist/core/artifact-graph/index.d.ts +8 -0
  53. package/dist/core/artifact-graph/index.js +14 -0
  54. package/dist/core/artifact-graph/instruction-loader.d.ts +196 -0
  55. package/dist/core/artifact-graph/instruction-loader.js +317 -0
  56. package/dist/core/artifact-graph/outputs.d.ts +14 -0
  57. package/dist/core/artifact-graph/outputs.js +39 -0
  58. package/dist/core/artifact-graph/resolver.d.ts +81 -0
  59. package/dist/core/artifact-graph/resolver.js +257 -0
  60. package/dist/core/artifact-graph/schema.d.ts +13 -0
  61. package/dist/core/artifact-graph/schema.js +108 -0
  62. package/dist/core/artifact-graph/state.d.ts +12 -0
  63. package/dist/core/artifact-graph/state.js +31 -0
  64. package/dist/core/artifact-graph/types.d.ts +47 -0
  65. package/dist/core/artifact-graph/types.js +48 -0
  66. package/dist/core/available-tools.d.ts +17 -0
  67. package/dist/core/available-tools.js +43 -0
  68. package/dist/core/command-generation/adapters/amazon-q.d.ts +13 -0
  69. package/dist/core/command-generation/adapters/amazon-q.js +26 -0
  70. package/dist/core/command-generation/adapters/antigravity.d.ts +13 -0
  71. package/dist/core/command-generation/adapters/antigravity.js +26 -0
  72. package/dist/core/command-generation/adapters/auggie.d.ts +13 -0
  73. package/dist/core/command-generation/adapters/auggie.js +27 -0
  74. package/dist/core/command-generation/adapters/bob.d.ts +14 -0
  75. package/dist/core/command-generation/adapters/bob.js +45 -0
  76. package/dist/core/command-generation/adapters/claude.d.ts +13 -0
  77. package/dist/core/command-generation/adapters/claude.js +50 -0
  78. package/dist/core/command-generation/adapters/cline.d.ts +14 -0
  79. package/dist/core/command-generation/adapters/cline.js +27 -0
  80. package/dist/core/command-generation/adapters/codebuddy.d.ts +13 -0
  81. package/dist/core/command-generation/adapters/codebuddy.js +28 -0
  82. package/dist/core/command-generation/adapters/codex.d.ts +16 -0
  83. package/dist/core/command-generation/adapters/codex.js +39 -0
  84. package/dist/core/command-generation/adapters/continue.d.ts +13 -0
  85. package/dist/core/command-generation/adapters/continue.js +28 -0
  86. package/dist/core/command-generation/adapters/costrict.d.ts +13 -0
  87. package/dist/core/command-generation/adapters/costrict.js +27 -0
  88. package/dist/core/command-generation/adapters/crush.d.ts +13 -0
  89. package/dist/core/command-generation/adapters/crush.js +30 -0
  90. package/dist/core/command-generation/adapters/cursor.d.ts +14 -0
  91. package/dist/core/command-generation/adapters/cursor.js +44 -0
  92. package/dist/core/command-generation/adapters/factory.d.ts +13 -0
  93. package/dist/core/command-generation/adapters/factory.js +27 -0
  94. package/dist/core/command-generation/adapters/gemini.d.ts +13 -0
  95. package/dist/core/command-generation/adapters/gemini.js +26 -0
  96. package/dist/core/command-generation/adapters/github-copilot.d.ts +13 -0
  97. package/dist/core/command-generation/adapters/github-copilot.js +26 -0
  98. package/dist/core/command-generation/adapters/iflow.d.ts +13 -0
  99. package/dist/core/command-generation/adapters/iflow.js +29 -0
  100. package/dist/core/command-generation/adapters/index.d.ts +32 -0
  101. package/dist/core/command-generation/adapters/index.js +32 -0
  102. package/dist/core/command-generation/adapters/junie.d.ts +13 -0
  103. package/dist/core/command-generation/adapters/junie.js +26 -0
  104. package/dist/core/command-generation/adapters/kilocode.d.ts +14 -0
  105. package/dist/core/command-generation/adapters/kilocode.js +23 -0
  106. package/dist/core/command-generation/adapters/kiro.d.ts +13 -0
  107. package/dist/core/command-generation/adapters/kiro.js +26 -0
  108. package/dist/core/command-generation/adapters/lingma.d.ts +13 -0
  109. package/dist/core/command-generation/adapters/lingma.js +30 -0
  110. package/dist/core/command-generation/adapters/opencode.d.ts +13 -0
  111. package/dist/core/command-generation/adapters/opencode.js +29 -0
  112. package/dist/core/command-generation/adapters/pi.d.ts +18 -0
  113. package/dist/core/command-generation/adapters/pi.js +55 -0
  114. package/dist/core/command-generation/adapters/qoder.d.ts +13 -0
  115. package/dist/core/command-generation/adapters/qoder.js +30 -0
  116. package/dist/core/command-generation/adapters/qwen.d.ts +13 -0
  117. package/dist/core/command-generation/adapters/qwen.js +26 -0
  118. package/dist/core/command-generation/adapters/roocode.d.ts +14 -0
  119. package/dist/core/command-generation/adapters/roocode.js +27 -0
  120. package/dist/core/command-generation/adapters/windsurf.d.ts +14 -0
  121. package/dist/core/command-generation/adapters/windsurf.js +51 -0
  122. package/dist/core/command-generation/generator.d.ts +21 -0
  123. package/dist/core/command-generation/generator.js +27 -0
  124. package/dist/core/command-generation/index.d.ts +22 -0
  125. package/dist/core/command-generation/index.js +24 -0
  126. package/dist/core/command-generation/registry.d.ts +36 -0
  127. package/dist/core/command-generation/registry.js +98 -0
  128. package/dist/core/command-generation/types.d.ts +56 -0
  129. package/dist/core/command-generation/types.js +8 -0
  130. package/dist/core/completions/command-registry.d.ts +7 -0
  131. package/dist/core/completions/command-registry.js +626 -0
  132. package/dist/core/completions/completion-provider.d.ts +71 -0
  133. package/dist/core/completions/completion-provider.js +129 -0
  134. package/dist/core/completions/factory.d.ts +64 -0
  135. package/dist/core/completions/factory.js +75 -0
  136. package/dist/core/completions/generators/bash-generator.d.ts +35 -0
  137. package/dist/core/completions/generators/bash-generator.js +230 -0
  138. package/dist/core/completions/generators/fish-generator.d.ts +32 -0
  139. package/dist/core/completions/generators/fish-generator.js +160 -0
  140. package/dist/core/completions/generators/powershell-generator.d.ts +36 -0
  141. package/dist/core/completions/generators/powershell-generator.js +266 -0
  142. package/dist/core/completions/generators/zsh-generator.d.ts +47 -0
  143. package/dist/core/completions/generators/zsh-generator.js +274 -0
  144. package/dist/core/completions/installers/bash-installer.d.ts +87 -0
  145. package/dist/core/completions/installers/bash-installer.js +318 -0
  146. package/dist/core/completions/installers/fish-installer.d.ts +43 -0
  147. package/dist/core/completions/installers/fish-installer.js +143 -0
  148. package/dist/core/completions/installers/powershell-installer.d.ts +102 -0
  149. package/dist/core/completions/installers/powershell-installer.js +387 -0
  150. package/dist/core/completions/installers/zsh-installer.d.ts +117 -0
  151. package/dist/core/completions/installers/zsh-installer.js +421 -0
  152. package/dist/core/completions/templates/bash-templates.d.ts +6 -0
  153. package/dist/core/completions/templates/bash-templates.js +30 -0
  154. package/dist/core/completions/templates/fish-templates.d.ts +7 -0
  155. package/dist/core/completions/templates/fish-templates.js +45 -0
  156. package/dist/core/completions/templates/powershell-templates.d.ts +6 -0
  157. package/dist/core/completions/templates/powershell-templates.js +34 -0
  158. package/dist/core/completions/templates/zsh-templates.d.ts +6 -0
  159. package/dist/core/completions/templates/zsh-templates.js +45 -0
  160. package/dist/core/completions/types.d.ts +101 -0
  161. package/dist/core/completions/types.js +2 -0
  162. package/dist/core/config-prompts.d.ts +9 -0
  163. package/dist/core/config-prompts.js +34 -0
  164. package/dist/core/config-schema.d.ts +86 -0
  165. package/dist/core/config-schema.js +213 -0
  166. package/dist/core/config.d.ts +18 -0
  167. package/dist/core/config.js +38 -0
  168. package/dist/core/converters/json-converter.d.ts +6 -0
  169. package/dist/core/converters/json-converter.js +51 -0
  170. package/dist/core/global-config.d.ts +49 -0
  171. package/dist/core/global-config.js +124 -0
  172. package/dist/core/index.d.ts +5 -0
  173. package/dist/core/index.js +6 -0
  174. package/dist/core/init.d.ts +37 -0
  175. package/dist/core/init.js +593 -0
  176. package/dist/core/jira/config.d.ts +35 -0
  177. package/dist/core/jira/config.js +151 -0
  178. package/dist/core/jira/constants.d.ts +20 -0
  179. package/dist/core/jira/constants.js +49 -0
  180. package/dist/core/jira/doctor.d.ts +19 -0
  181. package/dist/core/jira/doctor.js +173 -0
  182. package/dist/core/jira/hash.d.ts +3 -0
  183. package/dist/core/jira/hash.js +9 -0
  184. package/dist/core/jira/index.d.ts +11 -0
  185. package/dist/core/jira/index.js +11 -0
  186. package/dist/core/jira/intake.d.ts +40 -0
  187. package/dist/core/jira/intake.js +54 -0
  188. package/dist/core/jira/mcp-config.d.ts +13 -0
  189. package/dist/core/jira/mcp-config.js +259 -0
  190. package/dist/core/jira/paths.d.ts +12 -0
  191. package/dist/core/jira/paths.js +66 -0
  192. package/dist/core/jira/setup.d.ts +30 -0
  193. package/dist/core/jira/setup.js +99 -0
  194. package/dist/core/jira/templates.d.ts +12 -0
  195. package/dist/core/jira/templates.js +204 -0
  196. package/dist/core/jira/validation.d.ts +17 -0
  197. package/dist/core/jira/validation.js +341 -0
  198. package/dist/core/legacy-cleanup.d.ts +162 -0
  199. package/dist/core/legacy-cleanup.js +514 -0
  200. package/dist/core/list.d.ts +9 -0
  201. package/dist/core/list.js +171 -0
  202. package/dist/core/migration.d.ts +23 -0
  203. package/dist/core/migration.js +108 -0
  204. package/dist/core/parsers/change-parser.d.ts +13 -0
  205. package/dist/core/parsers/change-parser.js +197 -0
  206. package/dist/core/parsers/markdown-parser.d.ts +26 -0
  207. package/dist/core/parsers/markdown-parser.js +227 -0
  208. package/dist/core/parsers/requirement-blocks.d.ts +37 -0
  209. package/dist/core/parsers/requirement-blocks.js +201 -0
  210. package/dist/core/parsers/spec-structure.d.ts +9 -0
  211. package/dist/core/parsers/spec-structure.js +88 -0
  212. package/dist/core/planning-home.d.ts +21 -0
  213. package/dist/core/planning-home.js +124 -0
  214. package/dist/core/profile-sync-drift.d.ts +38 -0
  215. package/dist/core/profile-sync-drift.js +200 -0
  216. package/dist/core/profiles.d.ts +26 -0
  217. package/dist/core/profiles.js +40 -0
  218. package/dist/core/project-config.d.ts +64 -0
  219. package/dist/core/project-config.js +223 -0
  220. package/dist/core/schemas/base.schema.d.ts +13 -0
  221. package/dist/core/schemas/base.schema.js +13 -0
  222. package/dist/core/schemas/change.schema.d.ts +73 -0
  223. package/dist/core/schemas/change.schema.js +31 -0
  224. package/dist/core/schemas/index.d.ts +4 -0
  225. package/dist/core/schemas/index.js +4 -0
  226. package/dist/core/schemas/spec.schema.d.ts +18 -0
  227. package/dist/core/schemas/spec.schema.js +15 -0
  228. package/dist/core/shared/index.d.ts +8 -0
  229. package/dist/core/shared/index.js +8 -0
  230. package/dist/core/shared/skill-generation.d.ts +49 -0
  231. package/dist/core/shared/skill-generation.js +96 -0
  232. package/dist/core/shared/tool-detection.d.ts +71 -0
  233. package/dist/core/shared/tool-detection.js +158 -0
  234. package/dist/core/specs-apply.d.ts +73 -0
  235. package/dist/core/specs-apply.js +392 -0
  236. package/dist/core/styles/palette.d.ts +7 -0
  237. package/dist/core/styles/palette.js +8 -0
  238. package/dist/core/templates/index.d.ts +8 -0
  239. package/dist/core/templates/index.js +9 -0
  240. package/dist/core/templates/skill-templates.d.ts +19 -0
  241. package/dist/core/templates/skill-templates.js +18 -0
  242. package/dist/core/templates/types.d.ts +19 -0
  243. package/dist/core/templates/types.js +5 -0
  244. package/dist/core/templates/workflows/apply-change.d.ts +10 -0
  245. package/dist/core/templates/workflows/apply-change.js +314 -0
  246. package/dist/core/templates/workflows/archive-change.d.ts +10 -0
  247. package/dist/core/templates/workflows/archive-change.js +277 -0
  248. package/dist/core/templates/workflows/bulk-archive-change.d.ts +10 -0
  249. package/dist/core/templates/workflows/bulk-archive-change.js +492 -0
  250. package/dist/core/templates/workflows/continue-change.d.ts +10 -0
  251. package/dist/core/templates/workflows/continue-change.js +234 -0
  252. package/dist/core/templates/workflows/explore.d.ts +10 -0
  253. package/dist/core/templates/workflows/explore.js +459 -0
  254. package/dist/core/templates/workflows/feedback.d.ts +9 -0
  255. package/dist/core/templates/workflows/feedback.js +108 -0
  256. package/dist/core/templates/workflows/ff-change.d.ts +10 -0
  257. package/dist/core/templates/workflows/ff-change.js +200 -0
  258. package/dist/core/templates/workflows/new-change.d.ts +10 -0
  259. package/dist/core/templates/workflows/new-change.js +143 -0
  260. package/dist/core/templates/workflows/onboard.d.ts +10 -0
  261. package/dist/core/templates/workflows/onboard.js +563 -0
  262. package/dist/core/templates/workflows/propose.d.ts +10 -0
  263. package/dist/core/templates/workflows/propose.js +218 -0
  264. package/dist/core/templates/workflows/sync-specs.d.ts +10 -0
  265. package/dist/core/templates/workflows/sync-specs.js +290 -0
  266. package/dist/core/templates/workflows/verify-change.d.ts +10 -0
  267. package/dist/core/templates/workflows/verify-change.js +338 -0
  268. package/dist/core/update.d.ts +83 -0
  269. package/dist/core/update.js +573 -0
  270. package/dist/core/validation/constants.d.ts +34 -0
  271. package/dist/core/validation/constants.js +40 -0
  272. package/dist/core/validation/types.d.ts +18 -0
  273. package/dist/core/validation/types.js +2 -0
  274. package/dist/core/validation/validator.d.ts +33 -0
  275. package/dist/core/validation/validator.js +418 -0
  276. package/dist/core/view.d.ts +8 -0
  277. package/dist/core/view.js +168 -0
  278. package/dist/core/workspace/foundation.d.ts +87 -0
  279. package/dist/core/workspace/foundation.js +379 -0
  280. package/dist/core/workspace/index.d.ts +6 -0
  281. package/dist/core/workspace/index.js +6 -0
  282. package/dist/core/workspace/link-input.d.ts +9 -0
  283. package/dist/core/workspace/link-input.js +32 -0
  284. package/dist/core/workspace/open-surface.d.ts +24 -0
  285. package/dist/core/workspace/open-surface.js +137 -0
  286. package/dist/core/workspace/openers.d.ts +21 -0
  287. package/dist/core/workspace/openers.js +119 -0
  288. package/dist/core/workspace/skills.d.ts +55 -0
  289. package/dist/core/workspace/skills.js +334 -0
  290. package/dist/index.d.ts +3 -0
  291. package/dist/index.js +3 -0
  292. package/dist/prompts/searchable-multi-select.d.ts +28 -0
  293. package/dist/prompts/searchable-multi-select.js +159 -0
  294. package/dist/telemetry/config.d.ts +38 -0
  295. package/dist/telemetry/config.js +136 -0
  296. package/dist/telemetry/index.d.ts +31 -0
  297. package/dist/telemetry/index.js +164 -0
  298. package/dist/ui/ascii-patterns.d.ts +16 -0
  299. package/dist/ui/ascii-patterns.js +133 -0
  300. package/dist/ui/welcome-screen.d.ts +10 -0
  301. package/dist/ui/welcome-screen.js +146 -0
  302. package/dist/utils/change-metadata.d.ts +51 -0
  303. package/dist/utils/change-metadata.js +147 -0
  304. package/dist/utils/change-utils.d.ts +71 -0
  305. package/dist/utils/change-utils.js +123 -0
  306. package/dist/utils/command-references.d.ts +18 -0
  307. package/dist/utils/command-references.js +20 -0
  308. package/dist/utils/file-system.d.ts +41 -0
  309. package/dist/utils/file-system.js +301 -0
  310. package/dist/utils/index.d.ts +6 -0
  311. package/dist/utils/index.js +9 -0
  312. package/dist/utils/interactive.d.ts +18 -0
  313. package/dist/utils/interactive.js +21 -0
  314. package/dist/utils/item-discovery.d.ts +4 -0
  315. package/dist/utils/item-discovery.js +72 -0
  316. package/dist/utils/match.d.ts +3 -0
  317. package/dist/utils/match.js +22 -0
  318. package/dist/utils/shell-detection.d.ts +20 -0
  319. package/dist/utils/shell-detection.js +41 -0
  320. package/dist/utils/task-progress.d.ts +8 -0
  321. package/dist/utils/task-progress.js +36 -0
  322. package/package.json +79 -0
  323. package/schemas/spec-driven/schema.yaml +153 -0
  324. package/schemas/spec-driven/templates/design.md +19 -0
  325. package/schemas/spec-driven/templates/proposal.md +23 -0
  326. package/schemas/spec-driven/templates/spec.md +8 -0
  327. package/schemas/spec-driven/templates/tasks.md +9 -0
  328. package/schemas/workspace-planning/schema.yaml +72 -0
  329. package/schemas/workspace-planning/templates/design.md +33 -0
  330. package/schemas/workspace-planning/templates/proposal.md +28 -0
  331. package/schemas/workspace-planning/templates/spec.md +9 -0
  332. package/schemas/workspace-planning/templates/tasks.md +15 -0
  333. package/scripts/postinstall.js +83 -0
@@ -0,0 +1,151 @@
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import { promises as fs } from 'fs';
3
+ import path from 'path';
4
+ import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
5
+ import { z } from 'zod';
6
+ import { AI_TOOLS } from '../config.js';
7
+ import { JIRA_CONFIG_VERSION, JIRA_DEFAULT_ENDPOINT, JIRA_DEFAULT_PROVIDER, } from './constants.js';
8
+ import { getJiraConfigPath } from './paths.js';
9
+ export const JiraConfigSchema = z
10
+ .object({
11
+ version: z.number().int().positive().default(JIRA_CONFIG_VERSION),
12
+ provider: z.literal(JIRA_DEFAULT_PROVIDER).default(JIRA_DEFAULT_PROVIDER),
13
+ endpoint: z.string().url().default(JIRA_DEFAULT_ENDPOINT),
14
+ tools: z.array(z.string()).default([]),
15
+ issueTypes: z
16
+ .object({
17
+ epic: z.array(z.string()).default(['Epic']),
18
+ feature: z.array(z.string()).default(['Feature', 'Story']),
19
+ })
20
+ .default({ epic: ['Epic'], feature: ['Feature', 'Story'] }),
21
+ fields: z
22
+ .object({
23
+ summary: z.string().default('summary'),
24
+ description: z.string().default('description'),
25
+ acceptanceCriteria: z.string().default('customfield_*'),
26
+ })
27
+ .default({
28
+ summary: 'summary',
29
+ description: 'description',
30
+ acceptanceCriteria: 'customfield_*',
31
+ }),
32
+ writeback: z
33
+ .object({
34
+ enabled: z.boolean().default(false),
35
+ requireConfirmation: z.boolean().default(true),
36
+ })
37
+ .default({ enabled: false, requireConfirmation: true }),
38
+ })
39
+ .passthrough();
40
+ export function createDefaultJiraConfig(tools = []) {
41
+ return JiraConfigSchema.parse({ tools });
42
+ }
43
+ export function readJiraConfig(projectRoot) {
44
+ const configPath = getJiraConfigPath(projectRoot);
45
+ const warnings = [];
46
+ if (!existsSync(configPath)) {
47
+ return { config: null, path: configPath, warnings };
48
+ }
49
+ try {
50
+ const rawContent = readFileSync(configPath, 'utf8');
51
+ const raw = parseYaml(rawContent);
52
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) {
53
+ warnings.push('openspec/jira.yaml must be a YAML object');
54
+ return { config: null, path: configPath, warnings };
55
+ }
56
+ const parsed = JiraConfigSchema.safeParse(raw);
57
+ if (!parsed.success) {
58
+ warnings.push(...parsed.error.issues.map((issue) => `${issue.path.join('.') || 'config'}: ${issue.message}`));
59
+ return { config: null, path: configPath, warnings };
60
+ }
61
+ warnings.push(...getJiraConfigWarnings(parsed.data));
62
+ return { config: parsed.data, path: configPath, warnings };
63
+ }
64
+ catch (error) {
65
+ warnings.push(`Failed to parse openspec/jira.yaml: ${error instanceof Error ? error.message : String(error)}`);
66
+ return { config: null, path: configPath, warnings };
67
+ }
68
+ }
69
+ export function getJiraConfigWarnings(config) {
70
+ const warnings = [];
71
+ if (config.endpoint.includes('/v1/sse')) {
72
+ warnings.push('Atlassian Rovo MCP /v1/sse endpoint is deprecated; use https://mcp.atlassian.com/v1/mcp/authv2.');
73
+ }
74
+ else if (config.endpoint === 'https://mcp.atlassian.com/v1/mcp') {
75
+ warnings.push('Atlassian Rovo MCP /v1/mcp endpoint is outdated; use https://mcp.atlassian.com/v1/mcp/authv2.');
76
+ }
77
+ const validToolIds = new Set(AI_TOOLS.filter((tool) => tool.skillsDir).map((tool) => tool.value));
78
+ for (const tool of config.tools) {
79
+ if (!validToolIds.has(tool)) {
80
+ warnings.push(`Unknown or unsupported AI tool in jira.yaml: ${tool}`);
81
+ }
82
+ }
83
+ if (containsSecretLikeKey(config)) {
84
+ warnings.push('openspec/jira.yaml contains secret-like keys; setup will not preserve token, secret, password, or OAuth credential fields.');
85
+ }
86
+ return warnings;
87
+ }
88
+ export async function writeJiraConfig(projectRoot, config, options = {}) {
89
+ const configPath = getJiraConfigPath(projectRoot);
90
+ const existing = existsSync(configPath) ? parseExistingConfig(configPath) : {};
91
+ const merged = sanitizeSecretLikeKeys({ ...existing, ...config });
92
+ const parsed = JiraConfigSchema.parse(merged);
93
+ if (existsSync(configPath) && !options.force) {
94
+ const existingContent = readFileSync(configPath, 'utf8');
95
+ const nextContent = serializeJiraConfig(parsed);
96
+ if (existingContent.trim() === nextContent.trim()) {
97
+ return configPath;
98
+ }
99
+ }
100
+ await fs.mkdir(path.dirname(configPath), { recursive: true });
101
+ await fs.writeFile(configPath, serializeJiraConfig(parsed), 'utf8');
102
+ return configPath;
103
+ }
104
+ export function serializeJiraConfig(config) {
105
+ return stringifyYaml(sanitizeSecretLikeKeys(config), { lineWidth: 0 });
106
+ }
107
+ function parseExistingConfig(configPath) {
108
+ try {
109
+ const raw = parseYaml(readFileSync(configPath, 'utf8'));
110
+ if (raw && typeof raw === 'object' && !Array.isArray(raw)) {
111
+ return raw;
112
+ }
113
+ }
114
+ catch {
115
+ // Ignore invalid existing config during setup; schema parsing will rewrite a safe file.
116
+ }
117
+ return {};
118
+ }
119
+ function isSecretLikeKey(key) {
120
+ return /(token|secret|password|clientsecret|apikey|api_key|oauth)/i.test(key);
121
+ }
122
+ export function sanitizeSecretLikeKeys(value) {
123
+ if (Array.isArray(value)) {
124
+ return value.map((item) => sanitizeSecretLikeKeys(item));
125
+ }
126
+ if (value && typeof value === 'object') {
127
+ const output = {};
128
+ for (const [key, child] of Object.entries(value)) {
129
+ if (isSecretLikeKey(key))
130
+ continue;
131
+ output[key] = sanitizeSecretLikeKeys(child);
132
+ }
133
+ return output;
134
+ }
135
+ return value;
136
+ }
137
+ function containsSecretLikeKey(value) {
138
+ if (Array.isArray(value)) {
139
+ return value.some((item) => containsSecretLikeKey(item));
140
+ }
141
+ if (value && typeof value === 'object') {
142
+ for (const [key, child] of Object.entries(value)) {
143
+ if (isSecretLikeKey(key))
144
+ return true;
145
+ if (containsSecretLikeKey(child))
146
+ return true;
147
+ }
148
+ }
149
+ return false;
150
+ }
151
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,20 @@
1
+ export declare const JIRA_DIR_NAME = "jira";
2
+ export declare const JIRA_CONFIG_FILE = "jira.yaml";
3
+ export declare const JIRA_CONFIG_VERSION = 1;
4
+ export declare const JIRA_INTAKE_SCHEMA_VERSION = 1;
5
+ export declare const JIRA_DEFAULT_PROVIDER = "atlassian-rovo";
6
+ export declare const JIRA_DEFAULT_ENDPOINT = "https://mcp.atlassian.com/v1/mcp/authv2";
7
+ export declare const JIRA_WORKFLOW_IDS: readonly ["jira-import", "jira-refine", "jira-review", "jira-split", "jira-propose", "jira-sync"];
8
+ export type JiraWorkflowId = (typeof JIRA_WORKFLOW_IDS)[number];
9
+ export declare const JIRA_WORKFLOW_TO_SKILL_DIR: Record<JiraWorkflowId, string>;
10
+ export declare const JIRA_STATUS_ORDER: readonly ["imported", "refining", "ready-for-review", "reviewed", "split", "stories-reviewed", "proposed", "synced"];
11
+ export type JiraIntakeStatus = (typeof JIRA_STATUS_ORDER)[number];
12
+ export declare const JIRA_ALLOWED_NEXT: Record<JiraIntakeStatus, JiraIntakeStatus[]>;
13
+ export declare const JIRA_STAGE_MIN_STATUS: {
14
+ readonly source: "imported";
15
+ readonly requirement: "ready-for-review";
16
+ readonly stories: "stories-reviewed";
17
+ readonly propose: "proposed";
18
+ };
19
+ export type JiraValidationStage = keyof typeof JIRA_STAGE_MIN_STATUS;
20
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1,49 @@
1
+ export const JIRA_DIR_NAME = 'jira';
2
+ export const JIRA_CONFIG_FILE = 'jira.yaml';
3
+ export const JIRA_CONFIG_VERSION = 1;
4
+ export const JIRA_INTAKE_SCHEMA_VERSION = 1;
5
+ export const JIRA_DEFAULT_PROVIDER = 'atlassian-rovo';
6
+ export const JIRA_DEFAULT_ENDPOINT = 'https://mcp.atlassian.com/v1/mcp/authv2';
7
+ export const JIRA_WORKFLOW_IDS = [
8
+ 'jira-import',
9
+ 'jira-refine',
10
+ 'jira-review',
11
+ 'jira-split',
12
+ 'jira-propose',
13
+ 'jira-sync',
14
+ ];
15
+ export const JIRA_WORKFLOW_TO_SKILL_DIR = {
16
+ 'jira-import': 'openspec-jira-import',
17
+ 'jira-refine': 'openspec-jira-refine',
18
+ 'jira-review': 'openspec-jira-review',
19
+ 'jira-split': 'openspec-jira-split',
20
+ 'jira-propose': 'openspec-jira-propose',
21
+ 'jira-sync': 'openspec-jira-sync',
22
+ };
23
+ export const JIRA_STATUS_ORDER = [
24
+ 'imported',
25
+ 'refining',
26
+ 'ready-for-review',
27
+ 'reviewed',
28
+ 'split',
29
+ 'stories-reviewed',
30
+ 'proposed',
31
+ 'synced',
32
+ ];
33
+ export const JIRA_ALLOWED_NEXT = {
34
+ imported: ['refining'],
35
+ refining: ['ready-for-review'],
36
+ 'ready-for-review': ['reviewed'],
37
+ reviewed: ['split'],
38
+ split: ['stories-reviewed'],
39
+ 'stories-reviewed': ['proposed'],
40
+ proposed: ['synced'],
41
+ synced: [],
42
+ };
43
+ export const JIRA_STAGE_MIN_STATUS = {
44
+ source: 'imported',
45
+ requirement: 'ready-for-review',
46
+ stories: 'stories-reviewed',
47
+ propose: 'proposed',
48
+ };
49
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1,19 @@
1
+ import { type JiraMcpConfigResult } from './mcp-config.js';
2
+ export type JiraDoctorLevel = 'ok' | 'warning' | 'error' | 'manual-action-required';
3
+ export interface JiraDoctorCheck {
4
+ id: string;
5
+ level: JiraDoctorLevel;
6
+ message: string;
7
+ details?: string;
8
+ }
9
+ export interface JiraDoctorReport {
10
+ ok: boolean;
11
+ configPath: string;
12
+ checks: JiraDoctorCheck[];
13
+ tools: string[];
14
+ mcpConfigs: JiraMcpConfigResult[];
15
+ testPrompt: string;
16
+ mcpSnippet?: string;
17
+ }
18
+ export declare function runJiraDoctor(projectRoot: string): JiraDoctorReport;
19
+ //# sourceMappingURL=doctor.d.ts.map
@@ -0,0 +1,173 @@
1
+ import { existsSync } from 'fs';
2
+ import path from 'path';
3
+ import { spawnSync } from 'child_process';
4
+ import { AI_TOOLS } from '../config.js';
5
+ import { getAvailableTools } from '../available-tools.js';
6
+ import { CommandAdapterRegistry } from '../command-generation/index.js';
7
+ import { readJiraConfig } from './config.js';
8
+ import { JIRA_WORKFLOW_IDS, JIRA_WORKFLOW_TO_SKILL_DIR } from './constants.js';
9
+ import { inspectJiraMcpConfig } from './mcp-config.js';
10
+ import { getMcpSnippet } from './setup.js';
11
+ import { toDisplayPath } from './paths.js';
12
+ export function runJiraDoctor(projectRoot) {
13
+ const checks = [];
14
+ const { config, path: configPath, warnings } = readJiraConfig(projectRoot);
15
+ if (!config) {
16
+ checks.push({
17
+ id: 'jira-config',
18
+ level: 'error',
19
+ message: 'Missing or invalid openspec/jira.yaml.',
20
+ details: warnings.join('\n') || 'Run openspec jira setup first.',
21
+ });
22
+ return finish(configPath, checks, [], [], undefined);
23
+ }
24
+ checks.push({ id: 'jira-config', level: 'ok', message: 'Found openspec/jira.yaml.' });
25
+ for (const warning of warnings) {
26
+ checks.push({ id: 'jira-config-warning', level: 'warning', message: warning });
27
+ }
28
+ checks.push(checkNodeVersion());
29
+ checks.push(checkNpx());
30
+ if (config.endpoint.includes('/v1/sse')) {
31
+ checks.push({
32
+ id: 'mcp-endpoint',
33
+ level: 'warning',
34
+ message: 'Configured endpoint uses deprecated /v1/sse. Use https://mcp.atlassian.com/v1/mcp/authv2.',
35
+ });
36
+ }
37
+ else if (config.endpoint === 'https://mcp.atlassian.com/v1/mcp') {
38
+ checks.push({
39
+ id: 'mcp-endpoint',
40
+ level: 'warning',
41
+ message: 'Configured endpoint uses outdated /v1/mcp. Use https://mcp.atlassian.com/v1/mcp/authv2.',
42
+ });
43
+ }
44
+ else {
45
+ checks.push({ id: 'mcp-endpoint', level: 'ok', message: `MCP endpoint: ${config.endpoint}` });
46
+ }
47
+ const detected = new Set(getAvailableTools(projectRoot).map((tool) => tool.value));
48
+ if (detected.size === 0) {
49
+ checks.push({ id: 'detected-tools', level: 'warning', message: 'No AI tool directories detected in this project.' });
50
+ }
51
+ else {
52
+ checks.push({ id: 'detected-tools', level: 'ok', message: `Detected tools: ${[...detected].join(', ')}` });
53
+ }
54
+ for (const toolId of config.tools) {
55
+ checks.push(checkToolInstall(projectRoot, toolId));
56
+ }
57
+ const mcpConfigs = config.tools.map((toolId) => inspectJiraMcpConfig(projectRoot, toolId, config.endpoint));
58
+ for (const mcpConfig of mcpConfigs) {
59
+ checks.push(checkMcpConfig(mcpConfig));
60
+ }
61
+ checks.push({
62
+ id: 'jira-auth',
63
+ level: 'manual-action-required',
64
+ message: 'OAuth and Jira permissions must be verified inside your AI client.',
65
+ details: `Use the test prompt after restarting your AI client. MCP snippet:\n${getMcpSnippet(config.endpoint)}`,
66
+ });
67
+ return finish(configPath, checks, config.tools, mcpConfigs, getMcpSnippet(config.endpoint));
68
+ }
69
+ function finish(configPath, checks, tools, mcpConfigs, mcpSnippet) {
70
+ return {
71
+ ok: checks.every((check) => check.level !== 'error'),
72
+ configPath,
73
+ checks,
74
+ tools,
75
+ mcpConfigs,
76
+ mcpSnippet,
77
+ testPrompt: 'Use the Jira MCP server to read a harmless issue by id, then summarize summary, status, description, and acceptance criteria without writing to Jira.',
78
+ };
79
+ }
80
+ function checkMcpConfig(result) {
81
+ if (result.status === 'already-present') {
82
+ return { id: `mcp-${result.toolId}`, level: 'ok', message: result.message };
83
+ }
84
+ if (result.status === 'created') {
85
+ return {
86
+ id: `mcp-${result.toolId}`,
87
+ level: 'manual-action-required',
88
+ message: `Missing official Atlassian MCP config for ${result.toolId}. Run openspec jira setup --tools ${result.toolId} --force.`,
89
+ details: result.path,
90
+ };
91
+ }
92
+ if (result.status === 'updated') {
93
+ return {
94
+ id: `mcp-${result.toolId}`,
95
+ level: 'warning',
96
+ message: `Official Atlassian MCP config for ${result.toolId} needs refresh. Run openspec jira setup --tools ${result.toolId} --force.`,
97
+ details: result.message,
98
+ };
99
+ }
100
+ if (result.status === 'invalid-json') {
101
+ return {
102
+ id: `mcp-${result.toolId}`,
103
+ level: 'manual-action-required',
104
+ message: `Cannot inspect Atlassian MCP config for ${result.toolId}.`,
105
+ details: result.message,
106
+ };
107
+ }
108
+ return {
109
+ id: `mcp-${result.toolId}`,
110
+ level: 'manual-action-required',
111
+ message: `OpenSpec cannot auto-write official Atlassian MCP config for ${result.toolId}.`,
112
+ details: result.message,
113
+ };
114
+ }
115
+ function checkNodeVersion() {
116
+ const major = Number(process.versions.node.split('.')[0]);
117
+ if (Number.isFinite(major) && major >= 18) {
118
+ return { id: 'node-version', level: 'ok', message: `Node.js ${process.versions.node} is compatible with mcp-remote.` };
119
+ }
120
+ return {
121
+ id: 'node-version',
122
+ level: 'error',
123
+ message: `Node.js ${process.versions.node} is too old for mcp-remote; use Node.js 18 or newer.`,
124
+ };
125
+ }
126
+ function checkNpx() {
127
+ const result = spawnSync('npx', ['--version'], {
128
+ encoding: 'utf8',
129
+ shell: process.platform === 'win32',
130
+ });
131
+ if (result.status === 0) {
132
+ return { id: 'npx', level: 'ok', message: `npx is available (${result.stdout.trim()}).` };
133
+ }
134
+ return {
135
+ id: 'npx',
136
+ level: 'warning',
137
+ message: 'npx was not found; MCP clients using mcp-remote may fail until Node/npm tooling is installed.',
138
+ details: result.stderr?.trim(),
139
+ };
140
+ }
141
+ function checkToolInstall(projectRoot, toolId) {
142
+ const tool = AI_TOOLS.find((candidate) => candidate.value === toolId);
143
+ if (!tool?.skillsDir) {
144
+ return { id: `tool-${toolId}`, level: 'warning', message: `Unknown or unsupported configured tool: ${toolId}` };
145
+ }
146
+ const missing = [];
147
+ for (const workflowId of JIRA_WORKFLOW_IDS) {
148
+ const skillPath = path.join(projectRoot, tool.skillsDir, 'skills', JIRA_WORKFLOW_TO_SKILL_DIR[workflowId], 'SKILL.md');
149
+ if (!existsSync(skillPath)) {
150
+ missing.push(toDisplayPath(projectRoot, skillPath));
151
+ }
152
+ }
153
+ const adapter = CommandAdapterRegistry.get(toolId);
154
+ if (adapter) {
155
+ for (const workflowId of JIRA_WORKFLOW_IDS) {
156
+ const commandPath = adapter.getFilePath(workflowId);
157
+ const fullPath = path.isAbsolute(commandPath) ? commandPath : path.join(projectRoot, commandPath);
158
+ if (!existsSync(fullPath)) {
159
+ missing.push(path.isAbsolute(fullPath) ? fullPath : toDisplayPath(projectRoot, fullPath));
160
+ }
161
+ }
162
+ }
163
+ if (missing.length === 0) {
164
+ return { id: `tool-${toolId}`, level: 'ok', message: `Jira intake artifacts installed for ${tool.name}.` };
165
+ }
166
+ return {
167
+ id: `tool-${toolId}`,
168
+ level: 'manual-action-required',
169
+ message: `Jira intake artifacts are incomplete for ${tool.name}. Run openspec jira setup --tools ${toolId} --force.`,
170
+ details: missing.slice(0, 8).join('\n'),
171
+ };
172
+ }
173
+ //# sourceMappingURL=doctor.js.map
@@ -0,0 +1,3 @@
1
+ export declare function hashContentSha256(content: string): string;
2
+ export declare function hashFileSha256(filePath: string): string;
3
+ //# sourceMappingURL=hash.d.ts.map
@@ -0,0 +1,9 @@
1
+ import { createHash } from 'crypto';
2
+ import { readFileSync } from 'fs';
3
+ export function hashContentSha256(content) {
4
+ return createHash('sha256').update(content, 'utf8').digest('hex');
5
+ }
6
+ export function hashFileSha256(filePath) {
7
+ return hashContentSha256(readFileSync(filePath, 'utf8'));
8
+ }
9
+ //# sourceMappingURL=hash.js.map
@@ -0,0 +1,11 @@
1
+ export * from './config.js';
2
+ export * from './constants.js';
3
+ export * from './doctor.js';
4
+ export * from './hash.js';
5
+ export * from './intake.js';
6
+ export * from './mcp-config.js';
7
+ export * from './paths.js';
8
+ export * from './setup.js';
9
+ export * from './templates.js';
10
+ export * from './validation.js';
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,11 @@
1
+ export * from './config.js';
2
+ export * from './constants.js';
3
+ export * from './doctor.js';
4
+ export * from './hash.js';
5
+ export * from './intake.js';
6
+ export * from './mcp-config.js';
7
+ export * from './paths.js';
8
+ export * from './setup.js';
9
+ export * from './templates.js';
10
+ export * from './validation.js';
11
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,40 @@
1
+ import { z } from 'zod';
2
+ import { type JiraIntakeStatus } from './constants.js';
3
+ export declare const JiraIntakeSchema: z.ZodObject<{
4
+ schemaVersion: z.ZodDefault<z.ZodNumber>;
5
+ jira: z.ZodString;
6
+ status: z.ZodDefault<z.ZodEnum<{
7
+ split: "split";
8
+ imported: "imported";
9
+ refining: "refining";
10
+ "ready-for-review": "ready-for-review";
11
+ reviewed: "reviewed";
12
+ "stories-reviewed": "stories-reviewed";
13
+ proposed: "proposed";
14
+ synced: "synced";
15
+ }>>;
16
+ sourceHashSha256: z.ZodOptional<z.ZodString>;
17
+ allowedNext: z.ZodOptional<z.ZodArray<z.ZodEnum<{
18
+ split: "split";
19
+ imported: "imported";
20
+ refining: "refining";
21
+ "ready-for-review": "ready-for-review";
22
+ reviewed: "reviewed";
23
+ "stories-reviewed": "stories-reviewed";
24
+ proposed: "proposed";
25
+ synced: "synced";
26
+ }>>>;
27
+ }, z.core.$loose>;
28
+ export type JiraIntake = z.infer<typeof JiraIntakeSchema>;
29
+ export interface ReadJiraIntakeResult {
30
+ intake: JiraIntake | null;
31
+ issueDir: string;
32
+ path: string;
33
+ warnings: string[];
34
+ }
35
+ export declare function readJiraIntake(projectRoot: string, jiraId: string): ReadJiraIntakeResult;
36
+ export declare function getAllowedNext(status: JiraIntakeStatus): JiraIntakeStatus[];
37
+ export declare function canTransition(from: JiraIntakeStatus, to: JiraIntakeStatus): boolean;
38
+ export declare function compareStatus(a: JiraIntakeStatus, b: JiraIntakeStatus): number;
39
+ export declare function statusAtLeast(current: JiraIntakeStatus, required: JiraIntakeStatus): boolean;
40
+ //# sourceMappingURL=intake.d.ts.map
@@ -0,0 +1,54 @@
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import path from 'path';
3
+ import { parse as parseYaml } from 'yaml';
4
+ import { z } from 'zod';
5
+ import { JIRA_ALLOWED_NEXT, JIRA_INTAKE_SCHEMA_VERSION, JIRA_STATUS_ORDER, } from './constants.js';
6
+ import { getJiraIssueDir, normalizeJiraId } from './paths.js';
7
+ export const JiraIntakeSchema = z
8
+ .object({
9
+ schemaVersion: z.number().int().positive().default(JIRA_INTAKE_SCHEMA_VERSION),
10
+ jira: z.string().min(1),
11
+ status: z.enum(JIRA_STATUS_ORDER).default('imported'),
12
+ sourceHashSha256: z.string().optional(),
13
+ allowedNext: z.array(z.enum(JIRA_STATUS_ORDER)).optional(),
14
+ })
15
+ .passthrough();
16
+ export function readJiraIntake(projectRoot, jiraId) {
17
+ const issueDir = getJiraIssueDir(projectRoot, jiraId);
18
+ const intakePath = path.join(issueDir, 'intake.yaml');
19
+ const warnings = [];
20
+ if (!existsSync(intakePath)) {
21
+ return { intake: null, issueDir, path: intakePath, warnings };
22
+ }
23
+ try {
24
+ const raw = parseYaml(readFileSync(intakePath, 'utf8'));
25
+ const parsed = JiraIntakeSchema.safeParse(raw);
26
+ if (!parsed.success) {
27
+ warnings.push(...parsed.error.issues.map((issue) => `${issue.path.join('.') || 'intake'}: ${issue.message}`));
28
+ return { intake: null, issueDir, path: intakePath, warnings };
29
+ }
30
+ const expected = normalizeJiraId(jiraId);
31
+ const actual = normalizeJiraId(parsed.data.jira);
32
+ if (actual !== expected) {
33
+ warnings.push(`intake.yaml jira field is ${actual}, expected ${expected}`);
34
+ }
35
+ return { intake: parsed.data, issueDir, path: intakePath, warnings };
36
+ }
37
+ catch (error) {
38
+ warnings.push(`Failed to parse intake.yaml: ${error instanceof Error ? error.message : String(error)}`);
39
+ return { intake: null, issueDir, path: intakePath, warnings };
40
+ }
41
+ }
42
+ export function getAllowedNext(status) {
43
+ return JIRA_ALLOWED_NEXT[status];
44
+ }
45
+ export function canTransition(from, to) {
46
+ return JIRA_ALLOWED_NEXT[from].includes(to);
47
+ }
48
+ export function compareStatus(a, b) {
49
+ return JIRA_STATUS_ORDER.indexOf(a) - JIRA_STATUS_ORDER.indexOf(b);
50
+ }
51
+ export function statusAtLeast(current, required) {
52
+ return compareStatus(current, required) >= 0;
53
+ }
54
+ //# sourceMappingURL=intake.js.map
@@ -0,0 +1,13 @@
1
+ export type JiraMcpConfigStatus = 'created' | 'updated' | 'already-present' | 'unsupported' | 'invalid-json';
2
+ export interface JiraMcpConfigResult {
3
+ toolId: string;
4
+ status: JiraMcpConfigStatus;
5
+ path?: string;
6
+ serverName?: string;
7
+ message: string;
8
+ }
9
+ export declare function ensureJiraMcpConfigs(projectRoot: string, toolIds: string[], endpoint: string): Promise<JiraMcpConfigResult[]>;
10
+ export declare function ensureJiraMcpConfig(projectRoot: string, toolId: string, endpoint: string): Promise<JiraMcpConfigResult>;
11
+ export declare function inspectJiraMcpConfig(projectRoot: string, toolId: string, endpoint: string): JiraMcpConfigResult;
12
+ export declare function getManualJiraMcpSetupHint(toolId: string, endpoint: string): string;
13
+ //# sourceMappingURL=mcp-config.d.ts.map