@codewalla_india/openspec 1.3.1 → 1.3.3

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 -22
  2. package/README.md +214 -133
  3. package/bin/openspec.js +5 -5
  4. package/dist/cli/index.js +99 -62
  5. package/dist/commands/change.d.ts +0 -2
  6. package/dist/commands/change.js +107 -86
  7. package/dist/commands/config.js +14 -16
  8. package/dist/commands/doctor.js +9 -4
  9. package/dist/commands/feedback.js +79 -30
  10. package/dist/commands/modify.d.ts +26 -0
  11. package/dist/commands/modify.js +147 -0
  12. package/dist/commands/schema.js +170 -91
  13. package/dist/commands/show.js +5 -2
  14. package/dist/commands/spec.js +49 -29
  15. package/dist/commands/store.js +15 -21
  16. package/dist/commands/validate.d.ts +8 -0
  17. package/dist/commands/validate.js +43 -20
  18. package/dist/commands/workflow/index.d.ts +2 -2
  19. package/dist/commands/workflow/index.js +1 -1
  20. package/dist/commands/workflow/instructions.d.ts +6 -26
  21. package/dist/commands/workflow/instructions.js +183 -376
  22. package/dist/commands/workflow/new-change.d.ts +0 -4
  23. package/dist/commands/workflow/new-change.js +10 -28
  24. package/dist/commands/workflow/shared.d.ts +34 -19
  25. package/dist/commands/workflow/shared.js +34 -4
  26. package/dist/commands/workflow/status.js +10 -32
  27. package/dist/commands/workflow/templates.js +15 -5
  28. package/dist/commands/workset.d.ts +2 -2
  29. package/dist/commands/workset.js +19 -22
  30. package/dist/comprehension-quiz/fingerprint.d.ts +39 -0
  31. package/dist/comprehension-quiz/fingerprint.js +84 -0
  32. package/dist/comprehension-quiz/index.d.ts +42 -0
  33. package/dist/comprehension-quiz/index.js +47 -0
  34. package/dist/comprehension-quiz/pass-record.d.ts +44 -0
  35. package/dist/comprehension-quiz/pass-record.js +98 -0
  36. package/dist/comprehension-quiz/providers/anthropic.d.ts +35 -0
  37. package/dist/comprehension-quiz/providers/anthropic.js +69 -0
  38. package/dist/comprehension-quiz/providers/factory.d.ts +44 -0
  39. package/dist/comprehension-quiz/providers/factory.js +174 -0
  40. package/dist/comprehension-quiz/providers/interface.d.ts +98 -0
  41. package/dist/comprehension-quiz/providers/interface.js +150 -0
  42. package/dist/comprehension-quiz/providers/local.d.ts +35 -0
  43. package/dist/comprehension-quiz/providers/local.js +69 -0
  44. package/dist/comprehension-quiz/providers/ollama.d.ts +35 -0
  45. package/dist/comprehension-quiz/providers/ollama.js +69 -0
  46. package/dist/comprehension-quiz/providers/openai.d.ts +35 -0
  47. package/dist/comprehension-quiz/providers/openai.js +72 -0
  48. package/dist/comprehension-quiz/question-generator.d.ts +117 -0
  49. package/dist/comprehension-quiz/question-generator.js +203 -0
  50. package/dist/comprehension-quiz/quiz-executor.d.ts +75 -0
  51. package/dist/comprehension-quiz/quiz-executor.js +181 -0
  52. package/dist/comprehension-quiz/types.d.ts +137 -0
  53. package/dist/comprehension-quiz/types.js +11 -0
  54. package/dist/core/archive.d.ts +14 -1
  55. package/dist/core/archive.js +1350 -190
  56. package/dist/core/artifact-graph/graph.d.ts +28 -9
  57. package/dist/core/artifact-graph/graph.js +94 -43
  58. package/dist/core/artifact-graph/index.d.ts +1 -1
  59. package/dist/core/artifact-graph/index.js +1 -1
  60. package/dist/core/artifact-graph/instruction-loader.d.ts +30 -3
  61. package/dist/core/artifact-graph/instruction-loader.js +70 -12
  62. package/dist/core/artifact-graph/outputs.d.ts +1 -0
  63. package/dist/core/artifact-graph/outputs.js +67 -5
  64. package/dist/core/artifact-graph/resolver.d.ts +14 -0
  65. package/dist/core/artifact-graph/resolver.js +69 -15
  66. package/dist/core/artifact-graph/types.js +21 -3
  67. package/dist/core/available-tools.d.ts +2 -2
  68. package/dist/core/available-tools.js +14 -3
  69. package/dist/core/change-metadata/schema.d.ts +2 -0
  70. package/dist/core/change-metadata/schema.js +13 -0
  71. package/dist/core/change-status-policy.d.ts +10 -1
  72. package/dist/core/change-status-policy.js +30 -2
  73. package/dist/core/command-generation/adapters/amazon-q.d.ts +4 -0
  74. package/dist/core/command-generation/adapters/amazon-q.js +11 -5
  75. package/dist/core/command-generation/adapters/antigravity.js +6 -5
  76. package/dist/core/command-generation/adapters/auggie.js +7 -6
  77. package/dist/core/command-generation/adapters/bob.d.ts +5 -1
  78. package/dist/core/command-generation/adapters/bob.js +11 -10
  79. package/dist/core/command-generation/adapters/claude.d.ts +1 -1
  80. package/dist/core/command-generation/adapters/claude.js +12 -17
  81. package/dist/core/command-generation/adapters/cline.js +5 -5
  82. package/dist/core/command-generation/adapters/codebuddy.js +8 -7
  83. package/dist/core/command-generation/adapters/continue.js +8 -7
  84. package/dist/core/command-generation/adapters/costrict.js +7 -6
  85. package/dist/core/command-generation/adapters/crush.js +9 -9
  86. package/dist/core/command-generation/adapters/cursor.js +8 -8
  87. package/dist/core/command-generation/adapters/devin.d.ts +19 -0
  88. package/dist/core/command-generation/adapters/devin.js +36 -0
  89. package/dist/core/command-generation/adapters/factory.js +7 -6
  90. package/dist/core/command-generation/adapters/gemini.js +40 -5
  91. package/dist/core/command-generation/adapters/github-copilot.js +6 -5
  92. package/dist/core/command-generation/adapters/iflow.js +9 -8
  93. package/dist/core/command-generation/adapters/index.d.ts +4 -2
  94. package/dist/core/command-generation/adapters/index.js +4 -2
  95. package/dist/core/command-generation/adapters/junie.js +6 -5
  96. package/dist/core/command-generation/adapters/kilocode.js +1 -1
  97. package/dist/core/command-generation/adapters/kiro.js +6 -5
  98. package/dist/core/command-generation/adapters/lingma.js +9 -9
  99. package/dist/core/command-generation/adapters/oh-my-pi.d.ts +21 -0
  100. package/dist/core/command-generation/adapters/oh-my-pi.js +42 -0
  101. package/dist/core/command-generation/adapters/opencode.js +6 -8
  102. package/dist/core/command-generation/adapters/pi.d.ts +2 -2
  103. package/dist/core/command-generation/adapters/pi.js +7 -10
  104. package/dist/core/command-generation/adapters/qoder.js +9 -9
  105. package/dist/core/command-generation/adapters/qwen.d.ts +7 -3
  106. package/dist/core/command-generation/adapters/qwen.js +14 -9
  107. package/dist/core/command-generation/adapters/roocode.d.ts +4 -4
  108. package/dist/core/command-generation/adapters/roocode.js +9 -9
  109. package/dist/core/command-generation/adapters/trae.d.ts +13 -0
  110. package/dist/core/command-generation/adapters/trae.js +28 -0
  111. package/dist/core/command-generation/adapters/zcode.d.ts +16 -0
  112. package/dist/core/command-generation/adapters/zcode.js +33 -0
  113. package/dist/core/command-generation/generator.d.ts +8 -0
  114. package/dist/core/command-generation/generator.js +15 -1
  115. package/dist/core/command-generation/index.d.ts +1 -1
  116. package/dist/core/command-generation/index.js +1 -1
  117. package/dist/core/command-generation/invocation.d.ts +73 -0
  118. package/dist/core/command-generation/invocation.js +77 -0
  119. package/dist/core/command-generation/registry.js +8 -4
  120. package/dist/core/command-generation/types.d.ts +9 -2
  121. package/dist/core/command-generation/yaml.d.ts +20 -6
  122. package/dist/core/command-generation/yaml.js +31 -21
  123. package/dist/core/command-surface.d.ts +15 -0
  124. package/dist/core/command-surface.js +33 -0
  125. package/dist/core/completions/command-registry.js +16 -61
  126. package/dist/core/completions/generators/bash-generator.js +41 -41
  127. package/dist/core/completions/generators/fish-generator.js +7 -7
  128. package/dist/core/completions/generators/powershell-generator.js +44 -37
  129. package/dist/core/completions/generators/zsh-generator.js +33 -33
  130. package/dist/core/completions/installers/zsh-installer.d.ts +9 -0
  131. package/dist/core/completions/installers/zsh-installer.js +20 -4
  132. package/dist/core/completions/templates/bash-templates.js +24 -24
  133. package/dist/core/completions/templates/fish-templates.js +38 -38
  134. package/dist/core/completions/templates/powershell-templates.js +28 -28
  135. package/dist/core/completions/templates/zsh-templates.js +39 -39
  136. package/dist/core/config-prompts.d.ts +1 -1
  137. package/dist/core/config-prompts.js +14 -1
  138. package/dist/core/config-schema.d.ts +10 -1
  139. package/dist/core/config-schema.js +67 -1
  140. package/dist/core/config.d.ts +15 -0
  141. package/dist/core/config.js +46 -5
  142. package/dist/core/file-state.js +56 -24
  143. package/dist/core/github-copilot/cloud-agent.d.ts +95 -0
  144. package/dist/core/github-copilot/cloud-agent.js +497 -0
  145. package/dist/core/global-config.d.ts +16 -0
  146. package/dist/core/init.d.ts +58 -0
  147. package/dist/core/init.js +474 -73
  148. package/dist/core/legacy-cleanup.d.ts +59 -0
  149. package/dist/core/legacy-cleanup.js +253 -24
  150. package/dist/core/list.js +23 -16
  151. package/dist/core/migration.d.ts +73 -1
  152. package/dist/core/migration.js +360 -11
  153. package/dist/core/modify/conflict-detector.d.ts +26 -0
  154. package/dist/core/modify/conflict-detector.js +62 -0
  155. package/dist/core/modify/dependency-propagator.d.ts +38 -0
  156. package/dist/core/modify/dependency-propagator.js +103 -0
  157. package/dist/core/modify/history-tracker.d.ts +34 -0
  158. package/dist/core/modify/history-tracker.js +114 -0
  159. package/dist/core/modify/index.d.ts +7 -0
  160. package/dist/core/modify/index.js +7 -0
  161. package/dist/core/onboarding-commands.d.ts +30 -0
  162. package/dist/core/onboarding-commands.js +38 -0
  163. package/dist/core/openspec-root.js +18 -15
  164. package/dist/core/parsers/change-parser.d.ts +17 -2
  165. package/dist/core/parsers/change-parser.js +35 -21
  166. package/dist/core/parsers/code-fence.d.ts +15 -0
  167. package/dist/core/parsers/code-fence.js +49 -0
  168. package/dist/core/parsers/markdown-parser.d.ts +0 -3
  169. package/dist/core/parsers/markdown-parser.js +7 -60
  170. package/dist/core/parsers/requirement-blocks.d.ts +29 -0
  171. package/dist/core/parsers/requirement-blocks.js +150 -31
  172. package/dist/core/parsers/requirement-text.d.ts +48 -0
  173. package/dist/core/parsers/requirement-text.js +98 -0
  174. package/dist/core/parsers/spec-structure.d.ts +1 -1
  175. package/dist/core/parsers/spec-structure.js +20 -30
  176. package/dist/core/profile-sync-drift.d.ts +0 -8
  177. package/dist/core/profile-sync-drift.js +49 -50
  178. package/dist/core/profiles.d.ts +2 -2
  179. package/dist/core/profiles.js +2 -2
  180. package/dist/core/project-config.d.ts +27 -18
  181. package/dist/core/project-config.js +101 -34
  182. package/dist/core/references.js +42 -4
  183. package/dist/core/relationship-health.d.ts +8 -0
  184. package/dist/core/relationship-health.js +13 -0
  185. package/dist/core/root-selection.d.ts +9 -6
  186. package/dist/core/root-selection.js +42 -5
  187. package/dist/core/schemas/base.schema.js +7 -2
  188. package/dist/core/shared/allowed-tools.d.ts +12 -0
  189. package/dist/core/shared/allowed-tools.js +12 -0
  190. package/dist/core/shared/index.d.ts +1 -0
  191. package/dist/core/shared/index.js +1 -0
  192. package/dist/core/shared/skill-content-equivalence.d.ts +7 -0
  193. package/dist/core/shared/skill-content-equivalence.js +41 -0
  194. package/dist/core/shared/skill-generation.js +17 -13
  195. package/dist/core/shared/skill-paths.d.ts +13 -0
  196. package/dist/core/shared/skill-paths.js +23 -0
  197. package/dist/core/shared/tool-detection.d.ts +27 -7
  198. package/dist/core/shared/tool-detection.js +167 -37
  199. package/dist/core/shared-skill-target.d.ts +16 -0
  200. package/dist/core/shared-skill-target.js +156 -0
  201. package/dist/core/specs-apply.d.ts +80 -33
  202. package/dist/core/specs-apply.js +667 -145
  203. package/dist/core/store/git.d.ts +13 -0
  204. package/dist/core/store/git.js +24 -0
  205. package/dist/core/store/operations.js +20 -0
  206. package/dist/core/templates/skill-templates.d.ts +3 -2
  207. package/dist/core/templates/skill-templates.js +3 -2
  208. package/dist/core/templates/workflows/apply-change.d.ts +10 -0
  209. package/dist/core/templates/workflows/apply-change.js +186 -224
  210. package/dist/core/templates/workflows/archive-change.js +387 -260
  211. package/dist/core/templates/workflows/bulk-archive-change.js +655 -475
  212. package/dist/core/templates/workflows/continue-change.js +210 -219
  213. package/dist/core/templates/workflows/explore.js +479 -443
  214. package/dist/core/templates/workflows/feedback.js +97 -97
  215. package/dist/core/templates/workflows/ff-change.js +200 -191
  216. package/dist/core/templates/workflows/modify-change.d.ts +4 -1
  217. package/dist/core/templates/workflows/modify-change.js +193 -71
  218. package/dist/core/templates/workflows/new-change.js +127 -134
  219. package/dist/core/templates/workflows/onboard.js +548 -542
  220. package/dist/core/templates/workflows/propose.js +273 -217
  221. package/dist/core/templates/workflows/store-selection.d.ts +1 -1
  222. package/dist/core/templates/workflows/store-selection.js +1 -1
  223. package/dist/core/templates/workflows/sync-specs.js +500 -273
  224. package/dist/core/templates/workflows/update-change.d.ts +10 -0
  225. package/dist/core/templates/workflows/update-change.js +177 -0
  226. package/dist/core/templates/workflows/verify-change.js +324 -326
  227. package/dist/core/update.d.ts +40 -5
  228. package/dist/core/update.js +411 -96
  229. package/dist/core/validation/constants.d.ts +4 -1
  230. package/dist/core/validation/constants.js +4 -1
  231. package/dist/core/validation/plan-validator.d.ts +8 -0
  232. package/dist/core/validation/plan-validator.js +45 -0
  233. package/dist/core/validation/task-numbering.d.ts +16 -0
  234. package/dist/core/validation/task-numbering.js +57 -0
  235. package/dist/core/validation/validator.d.ts +27 -3
  236. package/dist/core/validation/validator.js +337 -48
  237. package/dist/core/version-check.d.ts +152 -0
  238. package/dist/core/version-check.js +731 -0
  239. package/dist/core/view.js +13 -18
  240. package/dist/prompts/searchable-multi-select.js +1 -1
  241. package/dist/telemetry/caller-detection.d.ts +27 -0
  242. package/dist/telemetry/caller-detection.js +85 -0
  243. package/dist/telemetry/caller-detection.test.d.ts +5 -0
  244. package/dist/telemetry/config.d.ts +48 -2
  245. package/dist/telemetry/config.js +113 -11
  246. package/dist/telemetry/config.test.d.ts +5 -0
  247. package/dist/telemetry/deduplication.d.ts +35 -0
  248. package/dist/telemetry/deduplication.js +82 -0
  249. package/dist/telemetry/deduplication.test.d.ts +5 -0
  250. package/dist/telemetry/identity.d.ts +62 -22
  251. package/dist/telemetry/identity.js +147 -102
  252. package/dist/telemetry/index.d.ts +126 -15
  253. package/dist/telemetry/index.js +569 -37
  254. package/dist/telemetry/sanitization.d.ts +40 -0
  255. package/dist/telemetry/sanitization.js +114 -0
  256. package/dist/telemetry/sanitization.test.d.ts +5 -0
  257. package/dist/telemetry/throttling.d.ts +20 -0
  258. package/dist/telemetry/throttling.js +70 -0
  259. package/dist/ui/welcome-screen.d.ts +9 -1
  260. package/dist/ui/welcome-screen.js +91 -38
  261. package/dist/utils/change-metadata.d.ts +43 -0
  262. package/dist/utils/change-metadata.js +123 -7
  263. package/dist/utils/change-utils.d.ts +10 -4
  264. package/dist/utils/change-utils.js +20 -13
  265. package/dist/utils/ci.d.ts +12 -0
  266. package/dist/utils/ci.js +16 -0
  267. package/dist/utils/command-references.d.ts +92 -6
  268. package/dist/utils/command-references.js +180 -7
  269. package/dist/utils/date.d.ts +8 -0
  270. package/dist/utils/date.js +13 -0
  271. package/dist/utils/file-system.d.ts +10 -0
  272. package/dist/utils/file-system.js +70 -0
  273. package/dist/utils/index.d.ts +1 -1
  274. package/dist/utils/index.js +1 -1
  275. package/dist/utils/interactive.d.ts +23 -0
  276. package/dist/utils/interactive.js +32 -0
  277. package/dist/utils/item-discovery.d.ts +19 -0
  278. package/dist/utils/item-discovery.js +30 -48
  279. package/dist/utils/shell-detection.d.ts +1 -1
  280. package/dist/utils/shell-detection.js +64 -11
  281. package/dist/utils/spec-discovery.d.ts +40 -0
  282. package/dist/utils/spec-discovery.js +115 -0
  283. package/dist/utils/task-progress.d.ts +29 -1
  284. package/dist/utils/task-progress.js +109 -15
  285. package/package.json +96 -84
  286. package/schemas/spec-driven/schema.yaml +252 -184
  287. package/schemas/spec-driven/templates/design.md +19 -19
  288. package/schemas/spec-driven/templates/plan-template.md +91 -0
  289. package/schemas/spec-driven/templates/proposal.md +29 -24
  290. package/schemas/spec-driven/templates/spec.md +11 -8
  291. package/schemas/spec-driven/templates/tasks.md +9 -9
  292. package/scripts/postinstall.js +83 -83
  293. package/dist/core/command-generation/adapters/codex.d.ts +0 -16
  294. package/dist/core/command-generation/adapters/codex.js +0 -39
  295. package/dist/core/command-generation/adapters/windsurf.d.ts +0 -14
  296. package/dist/core/command-generation/adapters/windsurf.js +0 -38
  297. package/dist/core/comprehension/config.d.ts +0 -20
  298. package/dist/core/comprehension/config.js +0 -23
  299. package/dist/core/comprehension/fingerprint.d.ts +0 -14
  300. package/dist/core/comprehension/fingerprint.js +0 -33
  301. package/dist/core/comprehension/index.d.ts +0 -57
  302. package/dist/core/comprehension/index.js +0 -87
  303. package/dist/core/comprehension/pass-record.d.ts +0 -29
  304. package/dist/core/comprehension/pass-record.js +0 -64
  305. package/dist/core/comprehension/stats.d.ts +0 -35
  306. package/dist/core/comprehension/stats.js +0 -133
  307. package/dist/core/templates/workflows/comprehension-guidance.d.ts +0 -9
  308. package/dist/core/templates/workflows/comprehension-guidance.js +0 -73
  309. package/dist/core/templates/workflows/mcp-guidance.d.ts +0 -13
  310. package/dist/core/templates/workflows/mcp-guidance.js +0 -131
  311. package/dist/core/templates/workflows/user-prompt-guidance.d.ts +0 -16
  312. package/dist/core/templates/workflows/user-prompt-guidance.js +0 -48
  313. package/dist/telemetry/caller.d.ts +0 -5
  314. package/dist/telemetry/caller.js +0 -29
  315. package/dist/telemetry/client.d.ts +0 -27
  316. package/dist/telemetry/client.js +0 -127
  317. package/dist/telemetry/command-context.d.ts +0 -13
  318. package/dist/telemetry/command-context.js +0 -59
  319. package/dist/telemetry/comprehension.d.ts +0 -44
  320. package/dist/telemetry/comprehension.js +0 -105
  321. package/dist/telemetry/content.d.ts +0 -10
  322. package/dist/telemetry/content.js +0 -56
  323. package/dist/telemetry/git-stats.d.ts +0 -12
  324. package/dist/telemetry/git-stats.js +0 -69
  325. package/dist/telemetry/identify-cache.d.ts +0 -7
  326. package/dist/telemetry/identify-cache.js +0 -47
  327. package/dist/telemetry/input.d.ts +0 -17
  328. package/dist/telemetry/input.js +0 -68
  329. package/dist/telemetry/marker.d.ts +0 -37
  330. package/dist/telemetry/marker.js +0 -67
  331. package/dist/telemetry/workflow.d.ts +0 -85
  332. package/dist/telemetry/workflow.js +0 -318
  333. package/schemas/spec-driven/templates/plan.md +0 -19
@@ -1,25 +1,30 @@
1
1
  /**
2
2
  * Qwen Code Command Adapter
3
3
  *
4
- * Formats commands for Qwen Code following its TOML specification.
4
+ * Formats commands for Qwen Code following its Markdown custom command
5
+ * specification. Qwen Code has deprecated TOML commands in favor of
6
+ * Markdown files with YAML frontmatter.
7
+ *
8
+ * @see https://qwenlm.github.io/qwen-code-docs/en/users/features/commands/#markdown-file-format-specification-recommended
5
9
  */
6
10
  import path from 'path';
11
+ import { escapeYamlValue } from '../yaml.js';
7
12
  /**
8
13
  * Qwen adapter for command generation.
9
- * File path: .qwen/commands/opsx-<id>.toml
10
- * Format: TOML with description and prompt fields
14
+ * File path: .qwen/commands/opsx-<id>.md
15
+ * Format: Markdown with description frontmatter
11
16
  */
12
17
  export const qwenAdapter = {
13
18
  toolId: 'qwen',
14
19
  getFilePath(commandId) {
15
- return path.join('.qwen', 'commands', `opsx-${commandId}.toml`);
20
+ return path.join('.qwen', 'commands', `opsx-${commandId}.md`);
16
21
  },
17
22
  formatFile(content) {
18
- return `description = "${content.description}"
19
-
20
- prompt = """
21
- ${content.body}
22
- """
23
+ return `---
24
+ description: ${escapeYamlValue(content.description)}
25
+ ---
26
+
27
+ ${content.body}
23
28
  `;
24
29
  },
25
30
  };
@@ -1,12 +1,12 @@
1
1
  /**
2
- * RooCode Command Adapter
2
+ * Zoo Code Command Adapter
3
3
  *
4
- * Formats commands for RooCode following its workflow specification.
5
- * RooCode uses markdown headers instead of YAML frontmatter.
4
+ * Formats commands for Zoo Code following its workflow specification.
5
+ * Zoo Code uses markdown headers instead of YAML frontmatter.
6
6
  */
7
7
  import type { ToolCommandAdapter } from '../types.js';
8
8
  /**
9
- * RooCode adapter for command generation.
9
+ * Zoo Code adapter for command generation.
10
10
  * File path: .roo/commands/opsx-<id>.md
11
11
  * Format: Markdown header with description
12
12
  */
@@ -1,12 +1,12 @@
1
1
  /**
2
- * RooCode Command Adapter
2
+ * Zoo Code Command Adapter
3
3
  *
4
- * Formats commands for RooCode following its workflow specification.
5
- * RooCode uses markdown headers instead of YAML frontmatter.
4
+ * Formats commands for Zoo Code following its workflow specification.
5
+ * Zoo Code uses markdown headers instead of YAML frontmatter.
6
6
  */
7
7
  import path from 'path';
8
8
  /**
9
- * RooCode adapter for command generation.
9
+ * Zoo Code adapter for command generation.
10
10
  * File path: .roo/commands/opsx-<id>.md
11
11
  * Format: Markdown header with description
12
12
  */
@@ -16,11 +16,11 @@ export const roocodeAdapter = {
16
16
  return path.join('.roo', 'commands', `opsx-${commandId}.md`);
17
17
  },
18
18
  formatFile(content) {
19
- return `# ${content.name}
20
-
21
- ${content.description}
22
-
23
- ${content.body}
19
+ return `# ${content.name}
20
+
21
+ ${content.description}
22
+
23
+ ${content.body}
24
24
  `;
25
25
  },
26
26
  };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Trae Command Adapter
3
+ *
4
+ * Formats commands for Trae IDE following its command specification.
5
+ */
6
+ import type { ToolCommandAdapter } from '../types.js';
7
+ /**
8
+ * Trae adapter for command generation.
9
+ * File path: .trae/commands/opsx-<id>.md
10
+ * Frontmatter: name, description
11
+ */
12
+ export declare const traeAdapter: ToolCommandAdapter;
13
+ //# sourceMappingURL=trae.d.ts.map
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Trae Command Adapter
3
+ *
4
+ * Formats commands for Trae IDE following its command specification.
5
+ */
6
+ import path from 'path';
7
+ import { escapeYamlValue } from '../yaml.js';
8
+ /**
9
+ * Trae adapter for command generation.
10
+ * File path: .trae/commands/opsx-<id>.md
11
+ * Frontmatter: name, description
12
+ */
13
+ export const traeAdapter = {
14
+ toolId: 'trae',
15
+ getFilePath(commandId) {
16
+ return path.join('.trae', 'commands', `opsx-${commandId}.md`);
17
+ },
18
+ formatFile(content) {
19
+ return `---
20
+ name: ${escapeYamlValue(content.name)}
21
+ description: ${escapeYamlValue(content.description)}
22
+ ---
23
+
24
+ ${content.body}
25
+ `;
26
+ },
27
+ };
28
+ //# sourceMappingURL=trae.js.map
@@ -0,0 +1,16 @@
1
+ /**
2
+ * ZCode Command Adapter
3
+ *
4
+ * Formats commands for ZCode following its frontmatter specification.
5
+ * ZCode shares Claude Code's command format conventions.
6
+ * File path: .zcode/commands/opsx/<id>.md
7
+ * Frontmatter: name, description, category, tags
8
+ */
9
+ import type { ToolCommandAdapter } from '../types.js';
10
+ /**
11
+ * ZCode adapter for command generation.
12
+ * File path: .zcode/commands/opsx/<id>.md
13
+ * Frontmatter: name, description, category, tags
14
+ */
15
+ export declare const zcodeAdapter: ToolCommandAdapter;
16
+ //# sourceMappingURL=zcode.d.ts.map
@@ -0,0 +1,33 @@
1
+ /**
2
+ * ZCode Command Adapter
3
+ *
4
+ * Formats commands for ZCode following its frontmatter specification.
5
+ * ZCode shares Claude Code's command format conventions.
6
+ * File path: .zcode/commands/opsx/<id>.md
7
+ * Frontmatter: name, description, category, tags
8
+ */
9
+ import path from 'path';
10
+ import { escapeYamlValue, formatTagsArray } from '../yaml.js';
11
+ /**
12
+ * ZCode adapter for command generation.
13
+ * File path: .zcode/commands/opsx/<id>.md
14
+ * Frontmatter: name, description, category, tags
15
+ */
16
+ export const zcodeAdapter = {
17
+ toolId: 'zcode',
18
+ getFilePath(commandId) {
19
+ return path.join('.zcode', 'commands', 'opsx', `${commandId}.md`);
20
+ },
21
+ formatFile(content) {
22
+ return `---
23
+ name: ${escapeYamlValue(content.name)}
24
+ description: ${escapeYamlValue(content.description)}
25
+ category: ${escapeYamlValue(content.category)}
26
+ tags: ${formatTagsArray(content.tags)}
27
+ ---
28
+
29
+ ${content.body}
30
+ `;
31
+ },
32
+ };
33
+ //# sourceMappingURL=zcode.js.map
@@ -6,6 +6,14 @@
6
6
  import type { CommandContent, ToolCommandAdapter, GeneratedCommand } from './types.js';
7
7
  /**
8
8
  * Generate a single command file using the provided adapter.
9
+ *
10
+ * Command bodies are authored with `/opsx:<id>` references. Tools whose command
11
+ * files are invoked by filename register `/opsx-<id>` instead, and Amazon Q
12
+ * surfaces them in its prompt library as `@opsx-<id>`, so the body is rewritten
13
+ * to the form that tool answers to before the adapter formats it. Doing it here
14
+ * rather than per adapter keeps every tool in step (#727, #1307); adapters stay
15
+ * pure formatters.
16
+ *
9
17
  * @param content - The tool-agnostic command content
10
18
  * @param adapter - The tool-specific adapter
11
19
  * @returns Generated command with path and file content
@@ -3,16 +3,30 @@
3
3
  *
4
4
  * Functions for generating command files using tool adapters.
5
5
  */
6
+ import { getInvocationForAdapter, needsInvocationRewrite } from './invocation.js';
7
+ import { transformCommandInvocations } from '../../utils/command-references.js';
6
8
  /**
7
9
  * Generate a single command file using the provided adapter.
10
+ *
11
+ * Command bodies are authored with `/opsx:<id>` references. Tools whose command
12
+ * files are invoked by filename register `/opsx-<id>` instead, and Amazon Q
13
+ * surfaces them in its prompt library as `@opsx-<id>`, so the body is rewritten
14
+ * to the form that tool answers to before the adapter formats it. Doing it here
15
+ * rather than per adapter keeps every tool in step (#727, #1307); adapters stay
16
+ * pure formatters.
17
+ *
8
18
  * @param content - The tool-agnostic command content
9
19
  * @param adapter - The tool-specific adapter
10
20
  * @returns Generated command with path and file content
11
21
  */
12
22
  export function generateCommand(content, adapter) {
23
+ const invocation = getInvocationForAdapter(adapter);
24
+ const formatted = needsInvocationRewrite(invocation)
25
+ ? { ...content, body: transformCommandInvocations(content.body, invocation) }
26
+ : content;
13
27
  return {
14
28
  path: adapter.getFilePath(content.id),
15
- fileContent: adapter.formatFile(content),
29
+ fileContent: adapter.formatFile(formatted),
16
30
  };
17
31
  }
18
32
  /**
@@ -18,5 +18,5 @@
18
18
  export type { CommandContent, ToolCommandAdapter, GeneratedCommand, } from './types.js';
19
19
  export { CommandAdapterRegistry } from './registry.js';
20
20
  export { generateCommand, generateCommands } from './generator.js';
21
- export { claudeAdapter, cursorAdapter, windsurfAdapter } from './adapters/index.js';
21
+ export { claudeAdapter, cursorAdapter, devinAdapter } from './adapters/index.js';
22
22
  //# sourceMappingURL=index.d.ts.map
@@ -20,5 +20,5 @@ export { CommandAdapterRegistry } from './registry.js';
20
20
  // Generator functions
21
21
  export { generateCommand, generateCommands } from './generator.js';
22
22
  // Adapters (for direct access if needed)
23
- export { claudeAdapter, cursorAdapter, windsurfAdapter } from './adapters/index.js';
23
+ export { claudeAdapter, cursorAdapter, devinAdapter } from './adapters/index.js';
24
24
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Command Invocation
3
+ *
4
+ * How a tool spells an OpenSpec command has two parts, and only one of them
5
+ * can be read off the file the adapter writes:
6
+ *
7
+ * - The *name* comes from the file. `.../commands/opsx/<id>.md` is namespaced
8
+ * by its directory, so the tool registers `opsx:<id>` (Claude Code, Gemini,
9
+ * Crush, ...). `.../commands/opsx-<id>.md` names the command with the
10
+ * filename, so the tool registers `opsx-<id>` (Cursor, GitHub Copilot,
11
+ * OpenCode, ...).
12
+ * - The *prefix* is the tool's own and cannot be derived. Almost every tool
13
+ * uses `/`; Amazon Q loads these files into its prompt library, which is
14
+ * invoked with `@` (`@opsx-propose`), so its adapter declares that prefix.
15
+ *
16
+ * Deriving the name from `getFilePath` keeps generated cross-references and
17
+ * onboarding hints in step with the files OpenSpec actually writes. A
18
+ * hand-maintained list drifted before: only OpenCode was rewritten when the
19
+ * hyphen form was introduced (#727), and Cursor still advertised `/opsx:`
20
+ * commands its palette never registered (#1307). Carrying the prefix as
21
+ * adapter metadata rather than inferring it keeps the one tool that does not
22
+ * use a slash from being advertised as if it did.
23
+ */
24
+ import type { ToolCommandAdapter } from './types.js';
25
+ export type CommandInvocationStyle = 'namespaced' | 'flat';
26
+ /**
27
+ * Everything needed to spell one of a tool's OpenSpec commands.
28
+ */
29
+ export interface CommandInvocation {
30
+ /** How the command file names the command. */
31
+ style: CommandInvocationStyle;
32
+ /** What the user types before the name, e.g. `/` or Amazon Q's `@`. */
33
+ prefix: string;
34
+ }
35
+ /** The form these docs, command bodies, and skill templates are authored in. */
36
+ export declare const CANONICAL_INVOCATION: CommandInvocation;
37
+ /**
38
+ * Classifies a generated command file by the name the tool will answer to.
39
+ *
40
+ * The test is the filename, not the directory: an `opsx-` prefix means the
41
+ * filename is the command. Every other shape is treated as namespaced, which
42
+ * is what all seven `opsx/<id>.*` adapters need. An adapter that neither
43
+ * prefixes the filename nor nests under `opsx/` would land here too — none
44
+ * does, and the registry-wide test in invocation.test.ts fails if one appears.
45
+ *
46
+ * @param commandFilePath - Path returned by an adapter's `getFilePath`
47
+ * @returns 'flat' when the filename carries the `opsx-` prefix, otherwise
48
+ * 'namespaced'
49
+ */
50
+ export declare function getInvocationStyleForPath(commandFilePath: string): CommandInvocationStyle;
51
+ /**
52
+ * Resolves how a tool's generated commands are invoked: the name from the
53
+ * files its adapter writes, the prefix from the adapter's own declaration.
54
+ *
55
+ * @param adapter - The tool-specific command adapter
56
+ * @returns The invocation shared by every command that adapter generates
57
+ */
58
+ export declare function getInvocationForAdapter(adapter: ToolCommandAdapter): CommandInvocation;
59
+ /**
60
+ * Spells one command the way the tool registers it.
61
+ *
62
+ * @param invocation - The tool's invocation, from getInvocationForAdapter()
63
+ * @param commandId - The command identifier (e.g. 'apply')
64
+ * @returns What the user types, e.g. `/opsx:apply`, `/opsx-apply`, `@opsx-apply`
65
+ */
66
+ export declare function formatCommandInvocation(invocation: CommandInvocation, commandId: string): string;
67
+ /**
68
+ * Whether a tool's invocation differs from the canonical `/opsx:<id>` that
69
+ * command bodies and skill templates are authored in — that is, whether
70
+ * generated text has to be rewritten for that tool at all.
71
+ */
72
+ export declare function needsInvocationRewrite(invocation: CommandInvocation): boolean;
73
+ //# sourceMappingURL=invocation.d.ts.map
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Command Invocation
3
+ *
4
+ * How a tool spells an OpenSpec command has two parts, and only one of them
5
+ * can be read off the file the adapter writes:
6
+ *
7
+ * - The *name* comes from the file. `.../commands/opsx/<id>.md` is namespaced
8
+ * by its directory, so the tool registers `opsx:<id>` (Claude Code, Gemini,
9
+ * Crush, ...). `.../commands/opsx-<id>.md` names the command with the
10
+ * filename, so the tool registers `opsx-<id>` (Cursor, GitHub Copilot,
11
+ * OpenCode, ...).
12
+ * - The *prefix* is the tool's own and cannot be derived. Almost every tool
13
+ * uses `/`; Amazon Q loads these files into its prompt library, which is
14
+ * invoked with `@` (`@opsx-propose`), so its adapter declares that prefix.
15
+ *
16
+ * Deriving the name from `getFilePath` keeps generated cross-references and
17
+ * onboarding hints in step with the files OpenSpec actually writes. A
18
+ * hand-maintained list drifted before: only OpenCode was rewritten when the
19
+ * hyphen form was introduced (#727), and Cursor still advertised `/opsx:`
20
+ * commands its palette never registered (#1307). Carrying the prefix as
21
+ * adapter metadata rather than inferring it keeps the one tool that does not
22
+ * use a slash from being advertised as if it did.
23
+ */
24
+ import path from 'path';
25
+ /** The form these docs, command bodies, and skill templates are authored in. */
26
+ export const CANONICAL_INVOCATION = { style: 'namespaced', prefix: '/' };
27
+ /**
28
+ * Classifies a generated command file by the name the tool will answer to.
29
+ *
30
+ * The test is the filename, not the directory: an `opsx-` prefix means the
31
+ * filename is the command. Every other shape is treated as namespaced, which
32
+ * is what all seven `opsx/<id>.*` adapters need. An adapter that neither
33
+ * prefixes the filename nor nests under `opsx/` would land here too — none
34
+ * does, and the registry-wide test in invocation.test.ts fails if one appears.
35
+ *
36
+ * @param commandFilePath - Path returned by an adapter's `getFilePath`
37
+ * @returns 'flat' when the filename carries the `opsx-` prefix, otherwise
38
+ * 'namespaced'
39
+ */
40
+ export function getInvocationStyleForPath(commandFilePath) {
41
+ return path.basename(commandFilePath).startsWith('opsx-') ? 'flat' : 'namespaced';
42
+ }
43
+ /**
44
+ * Resolves how a tool's generated commands are invoked: the name from the
45
+ * files its adapter writes, the prefix from the adapter's own declaration.
46
+ *
47
+ * @param adapter - The tool-specific command adapter
48
+ * @returns The invocation shared by every command that adapter generates
49
+ */
50
+ export function getInvocationForAdapter(adapter) {
51
+ return {
52
+ // Any command id works: every adapter applies one naming rule to all of them.
53
+ style: getInvocationStyleForPath(adapter.getFilePath('explore')),
54
+ prefix: adapter.invocationPrefix ?? CANONICAL_INVOCATION.prefix,
55
+ };
56
+ }
57
+ /**
58
+ * Spells one command the way the tool registers it.
59
+ *
60
+ * @param invocation - The tool's invocation, from getInvocationForAdapter()
61
+ * @param commandId - The command identifier (e.g. 'apply')
62
+ * @returns What the user types, e.g. `/opsx:apply`, `/opsx-apply`, `@opsx-apply`
63
+ */
64
+ export function formatCommandInvocation(invocation, commandId) {
65
+ const separator = invocation.style === 'namespaced' ? ':' : '-';
66
+ return `${invocation.prefix}opsx${separator}${commandId}`;
67
+ }
68
+ /**
69
+ * Whether a tool's invocation differs from the canonical `/opsx:<id>` that
70
+ * command bodies and skill templates are authored in — that is, whether
71
+ * generated text has to be rewritten for that tool at all.
72
+ */
73
+ export function needsInvocationRewrite(invocation) {
74
+ return (invocation.style !== CANONICAL_INVOCATION.style ||
75
+ invocation.prefix !== CANONICAL_INVOCATION.prefix);
76
+ }
77
+ //# sourceMappingURL=invocation.js.map
@@ -10,7 +10,7 @@ import { auggieAdapter } from './adapters/auggie.js';
10
10
  import { bobAdapter } from './adapters/bob.js';
11
11
  import { claudeAdapter } from './adapters/claude.js';
12
12
  import { clineAdapter } from './adapters/cline.js';
13
- import { codexAdapter } from './adapters/codex.js';
13
+ import { devinAdapter } from './adapters/devin.js';
14
14
  import { codebuddyAdapter } from './adapters/codebuddy.js';
15
15
  import { continueAdapter } from './adapters/continue.js';
16
16
  import { costrictAdapter } from './adapters/costrict.js';
@@ -23,13 +23,15 @@ import { iflowAdapter } from './adapters/iflow.js';
23
23
  import { junieAdapter } from './adapters/junie.js';
24
24
  import { kilocodeAdapter } from './adapters/kilocode.js';
25
25
  import { kiroAdapter } from './adapters/kiro.js';
26
+ import { ohMyPiAdapter } from './adapters/oh-my-pi.js';
26
27
  import { opencodeAdapter } from './adapters/opencode.js';
27
28
  import { piAdapter } from './adapters/pi.js';
28
29
  import { qoderAdapter } from './adapters/qoder.js';
29
30
  import { lingmaAdapter } from './adapters/lingma.js';
30
31
  import { qwenAdapter } from './adapters/qwen.js';
31
32
  import { roocodeAdapter } from './adapters/roocode.js';
32
- import { windsurfAdapter } from './adapters/windsurf.js';
33
+ import { traeAdapter } from './adapters/trae.js';
34
+ import { zcodeAdapter } from './adapters/zcode.js';
33
35
  /**
34
36
  * Registry for looking up tool command adapters.
35
37
  */
@@ -43,7 +45,7 @@ export class CommandAdapterRegistry {
43
45
  CommandAdapterRegistry.register(bobAdapter);
44
46
  CommandAdapterRegistry.register(claudeAdapter);
45
47
  CommandAdapterRegistry.register(clineAdapter);
46
- CommandAdapterRegistry.register(codexAdapter);
48
+ CommandAdapterRegistry.register(devinAdapter);
47
49
  CommandAdapterRegistry.register(codebuddyAdapter);
48
50
  CommandAdapterRegistry.register(continueAdapter);
49
51
  CommandAdapterRegistry.register(costrictAdapter);
@@ -56,13 +58,15 @@ export class CommandAdapterRegistry {
56
58
  CommandAdapterRegistry.register(junieAdapter);
57
59
  CommandAdapterRegistry.register(kilocodeAdapter);
58
60
  CommandAdapterRegistry.register(kiroAdapter);
61
+ CommandAdapterRegistry.register(ohMyPiAdapter);
59
62
  CommandAdapterRegistry.register(opencodeAdapter);
60
63
  CommandAdapterRegistry.register(piAdapter);
61
64
  CommandAdapterRegistry.register(qoderAdapter);
62
65
  CommandAdapterRegistry.register(lingmaAdapter);
63
66
  CommandAdapterRegistry.register(qwenAdapter);
64
67
  CommandAdapterRegistry.register(roocodeAdapter);
65
- CommandAdapterRegistry.register(windsurfAdapter);
68
+ CommandAdapterRegistry.register(traeAdapter);
69
+ CommandAdapterRegistry.register(zcodeAdapter);
66
70
  }
67
71
  /**
68
72
  * Register a tool command adapter.
@@ -34,9 +34,16 @@ export interface ToolCommandAdapter {
34
34
  * Returns the file path for a command.
35
35
  * @param commandId - The command identifier (e.g., 'explore')
36
36
  * @returns Path from project root (e.g., '.claude/commands/opsx/explore.md').
37
- * May be absolute for tools with global-scoped prompts (e.g., Codex).
37
+ * May be absolute for tools with global-scoped command files.
38
38
  */
39
39
  getFilePath(commandId: string): string;
40
+ /**
41
+ * What the user types before the command name, when it is not the default
42
+ * `/`. Amazon Q loads these files into its prompt library, which is invoked
43
+ * with `@` (`@opsx-propose`), so its adapter sets '@'. The name itself is
44
+ * still derived from getFilePath — see invocation.ts.
45
+ */
46
+ invocationPrefix?: string;
40
47
  /**
41
48
  * Formats the complete file content including frontmatter.
42
49
  * @param content - The tool-agnostic command content
@@ -48,7 +55,7 @@ export interface ToolCommandAdapter {
48
55
  * Result of generating a command file.
49
56
  */
50
57
  export interface GeneratedCommand {
51
- /** File path from project root, or absolute for global-scoped tools */
58
+ /** File path from project root, or absolute for global-scoped command files */
52
59
  path: string;
53
60
  /** Complete file content (frontmatter + body) */
54
61
  fileContent: string;
@@ -9,14 +9,28 @@
9
9
  /**
10
10
  * Escapes a string value for safe YAML output.
11
11
  *
12
- * Quotes the value with double quotes when it contains characters that
13
- * carry special meaning in YAML (or leading/trailing whitespace), and
14
- * escapes the characters that are not representable verbatim inside a
15
- * double-quoted scalar: backslash, double quote, line feed and carriage
16
- * return. Values without special characters are returned unquoted.
12
+ * Always emits a double-quoted scalar. Quoting unconditionally keeps the
13
+ * value a string no matter what it holds: an unquoted `true`, `null` or
14
+ * `123` would round-trip as a boolean, null or number, and an unquoted
15
+ * value opening with a block indicator (`|`, `>`) or containing `: `
16
+ * is not valid YAML at all.
17
+ *
18
+ * Inside the quotes it escapes everything that cannot appear verbatim in a
19
+ * double-quoted scalar: backslash, double quote, line feed, carriage
20
+ * return, and the non-printable characters YAML's `c-printable` production
21
+ * excludes (C0 controls, DEL and C1 controls). Lenient parsers accept a raw
22
+ * control byte, but strict ones reject the document outright, so escaping
23
+ * them here keeps the generated file portable across every tool's parser.
17
24
  *
18
25
  * @param value - The raw string to embed in YAML frontmatter.
19
- * @returns The value, double-quoted and escaped when necessary.
26
+ * @returns The value as an escaped, double-quoted YAML scalar.
20
27
  */
21
28
  export declare function escapeYamlValue(value: string): string;
29
+ /**
30
+ * Formats a tags array as a YAML array with proper escaping.
31
+ *
32
+ * @param tags - Array of tag strings.
33
+ * @returns Formatted YAML array string, e.g. '[tag1, tag2]'.
34
+ */
35
+ export declare function formatTagsArray(tags: string[]): string;
22
36
  //# sourceMappingURL=yaml.d.ts.map
@@ -9,30 +9,40 @@
9
9
  /**
10
10
  * Escapes a string value for safe YAML output.
11
11
  *
12
- * Quotes the value with double quotes when it contains characters that
13
- * carry special meaning in YAML (or leading/trailing whitespace), and
14
- * escapes the characters that are not representable verbatim inside a
15
- * double-quoted scalar: backslash, double quote, line feed and carriage
16
- * return. Values without special characters are returned unquoted.
12
+ * Always emits a double-quoted scalar. Quoting unconditionally keeps the
13
+ * value a string no matter what it holds: an unquoted `true`, `null` or
14
+ * `123` would round-trip as a boolean, null or number, and an unquoted
15
+ * value opening with a block indicator (`|`, `>`) or containing `: `
16
+ * is not valid YAML at all.
17
+ *
18
+ * Inside the quotes it escapes everything that cannot appear verbatim in a
19
+ * double-quoted scalar: backslash, double quote, line feed, carriage
20
+ * return, and the non-printable characters YAML's `c-printable` production
21
+ * excludes (C0 controls, DEL and C1 controls). Lenient parsers accept a raw
22
+ * control byte, but strict ones reject the document outright, so escaping
23
+ * them here keeps the generated file portable across every tool's parser.
17
24
  *
18
25
  * @param value - The raw string to embed in YAML frontmatter.
19
- * @returns The value, double-quoted and escaped when necessary.
26
+ * @returns The value as an escaped, double-quoted YAML scalar.
20
27
  */
21
28
  export function escapeYamlValue(value) {
22
- // Check if value needs quoting (contains special YAML characters or starts/ends with whitespace)
23
- const needsQuoting = /[:\n\r#{}[\],&*!|>'"%@`]|^\s|\s$/.test(value);
24
- if (needsQuoting) {
25
- // Use double quotes and escape characters that are not safe to emit
26
- // verbatim inside a double-quoted YAML scalar. Carriage returns must be
27
- // escaped too: a literal CR inside double quotes is subject to YAML line
28
- // folding/normalization and would silently corrupt the round-tripped value.
29
- const escaped = value
30
- .replace(/\\/g, '\\\\')
31
- .replace(/"/g, '\\"')
32
- .replace(/\n/g, '\\n')
33
- .replace(/\r/g, '\\r');
34
- return `"${escaped}"`;
35
- }
36
- return value;
29
+ const escaped = value
30
+ .replace(/\\/g, '\\\\')
31
+ .replace(/"/g, '\\"')
32
+ .replace(/\n/g, '\\n')
33
+ .replace(/\r/g, '\\r')
34
+ // Remaining non-printables have no dedicated escape; emit them as \xHH.
35
+ .replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/g, (char) => `\\x${char.charCodeAt(0).toString(16).padStart(2, '0')}`);
36
+ return `"${escaped}"`;
37
+ }
38
+ /**
39
+ * Formats a tags array as a YAML array with proper escaping.
40
+ *
41
+ * @param tags - Array of tag strings.
42
+ * @returns Formatted YAML array string, e.g. '[tag1, tag2]'.
43
+ */
44
+ export function formatTagsArray(tags) {
45
+ const escapedTags = tags.map((tag) => escapeYamlValue(tag));
46
+ return `[${escapedTags.join(', ')}]`;
37
47
  }
38
48
  //# sourceMappingURL=yaml.js.map
@@ -0,0 +1,15 @@
1
+ import { type CommandInvocation } from './command-generation/invocation.js';
2
+ import type { Delivery } from './global-config.js';
3
+ export type CommandSurfaceCapability = 'adapter-backed' | 'skills-invocable' | 'none';
4
+ /**
5
+ * How the tool spells its OpenSpec commands: the name from the command files
6
+ * its adapter writes, the prefix the adapter declares. Returns undefined for
7
+ * tools with no command adapter, which have no command names to spell.
8
+ */
9
+ export declare function resolveCommandInvocation(toolId: string): CommandInvocation | undefined;
10
+ export declare function resolveCommandSurfaceCapability(toolId: string): CommandSurfaceCapability;
11
+ export declare function shouldGenerateSkillsForTool(toolId: string, delivery: Delivery): boolean;
12
+ export declare function shouldRemoveSkillsForTool(toolId: string, delivery: Delivery): boolean;
13
+ export declare function shouldGenerateCommandsForTool(toolId: string, delivery: Delivery): boolean;
14
+ export declare function shouldReconcileCommandFilesForTool(toolId: string, delivery: Delivery): boolean;
15
+ //# sourceMappingURL=command-surface.d.ts.map
@@ -0,0 +1,33 @@
1
+ import { CommandAdapterRegistry } from './command-generation/index.js';
2
+ import { getInvocationForAdapter } from './command-generation/invocation.js';
3
+ /**
4
+ * How the tool spells its OpenSpec commands: the name from the command files
5
+ * its adapter writes, the prefix the adapter declares. Returns undefined for
6
+ * tools with no command adapter, which have no command names to spell.
7
+ */
8
+ export function resolveCommandInvocation(toolId) {
9
+ const adapter = CommandAdapterRegistry.get(toolId);
10
+ return adapter ? getInvocationForAdapter(adapter) : undefined;
11
+ }
12
+ export function resolveCommandSurfaceCapability(toolId) {
13
+ if (CommandAdapterRegistry.has(toolId)) {
14
+ return 'adapter-backed';
15
+ }
16
+ if (toolId === 'codex') {
17
+ return 'skills-invocable';
18
+ }
19
+ return 'none';
20
+ }
21
+ export function shouldGenerateSkillsForTool(toolId, delivery) {
22
+ return delivery !== 'commands' || resolveCommandSurfaceCapability(toolId) === 'skills-invocable';
23
+ }
24
+ export function shouldRemoveSkillsForTool(toolId, delivery) {
25
+ return delivery === 'commands' && resolveCommandSurfaceCapability(toolId) !== 'skills-invocable';
26
+ }
27
+ export function shouldGenerateCommandsForTool(toolId, delivery) {
28
+ return delivery !== 'skills' && resolveCommandSurfaceCapability(toolId) === 'adapter-backed';
29
+ }
30
+ export function shouldReconcileCommandFilesForTool(toolId, delivery) {
31
+ return delivery === 'skills' && resolveCommandSurfaceCapability(toolId) === 'adapter-backed';
32
+ }
33
+ //# sourceMappingURL=command-surface.js.map