sauron-cli 1.3.0 → 1.4.1

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 (655) hide show
  1. package/.genesis/prompts/CLI Init_ Atualiza/303/247/303/243o com Mem/303/263ria.md" +133 -0
  2. package/.genesis/prompts/prompt-sauron-update-intelligence.md +20 -0
  3. package/README.md +4 -2
  4. package/dist/index.js +59 -15
  5. package/package.json +1 -1
  6. package/templates/.agents/rules/memory.md +68 -68
  7. package/templates/.agents/skills/wiki/SKILL.md +14 -14
  8. package/55ea973d-e255-4f08-a313-a5d68243bd2d.png +0 -0
  9. package/OpenSpec-main/.actrc +0 -1
  10. package/OpenSpec-main/.changeset/README.md +0 -97
  11. package/OpenSpec-main/.changeset/config.json +0 -15
  12. package/OpenSpec-main/.coderabbit.yaml +0 -11
  13. package/OpenSpec-main/.devcontainer/README.md +0 -92
  14. package/OpenSpec-main/.devcontainer/devcontainer.json +0 -68
  15. package/OpenSpec-main/.github/CODEOWNERS +0 -2
  16. package/OpenSpec-main/.github/workflows/README.md +0 -20
  17. package/OpenSpec-main/.github/workflows/ci.yml +0 -346
  18. package/OpenSpec-main/.github/workflows/release-prepare.yml +0 -60
  19. package/OpenSpec-main/CHANGELOG.md +0 -594
  20. package/OpenSpec-main/LICENSE +0 -22
  21. package/OpenSpec-main/MAINTAINERS.md +0 -17
  22. package/OpenSpec-main/README.md +0 -206
  23. package/OpenSpec-main/README_OLD.md +0 -475
  24. package/OpenSpec-main/assets/openspec_bg.png +0 -0
  25. package/OpenSpec-main/assets/openspec_dashboard.png +0 -0
  26. package/OpenSpec-main/assets/openspec_pixel_dark.svg +0 -89
  27. package/OpenSpec-main/assets/openspec_pixel_light.svg +0 -89
  28. package/OpenSpec-main/bin/openspec.js +0 -5
  29. package/OpenSpec-main/build.js +0 -31
  30. package/OpenSpec-main/eslint.config.js +0 -42
  31. package/OpenSpec-main/flake.lock +0 -27
  32. package/OpenSpec-main/flake.nix +0 -114
  33. package/OpenSpec-main/openspec/changes/IMPLEMENTATION_ORDER.md +0 -68
  34. package/OpenSpec-main/openspec/changes/add-artifact-regeneration-support/proposal.md +0 -136
  35. package/OpenSpec-main/openspec/changes/add-change-stacking-awareness/.openspec.yaml +0 -2
  36. package/OpenSpec-main/openspec/changes/add-change-stacking-awareness/proposal.md +0 -93
  37. package/OpenSpec-main/openspec/changes/add-change-stacking-awareness/specs/change-creation/spec.md +0 -15
  38. package/OpenSpec-main/openspec/changes/add-change-stacking-awareness/specs/change-stacking-workflow/spec.md +0 -65
  39. package/OpenSpec-main/openspec/changes/add-change-stacking-awareness/specs/cli-change/spec.md +0 -27
  40. package/OpenSpec-main/openspec/changes/add-change-stacking-awareness/specs/openspec-conventions/spec.md +0 -29
  41. package/OpenSpec-main/openspec/changes/add-change-stacking-awareness/tasks.md +0 -39
  42. package/OpenSpec-main/openspec/changes/add-global-install-scope/.openspec.yaml +0 -2
  43. package/OpenSpec-main/openspec/changes/add-global-install-scope/design.md +0 -161
  44. package/OpenSpec-main/openspec/changes/add-global-install-scope/proposal.md +0 -101
  45. package/OpenSpec-main/openspec/changes/add-global-install-scope/specs/ai-tool-paths/spec.md +0 -35
  46. package/OpenSpec-main/openspec/changes/add-global-install-scope/specs/cli-config/spec.md +0 -21
  47. package/OpenSpec-main/openspec/changes/add-global-install-scope/specs/cli-init/spec.md +0 -28
  48. package/OpenSpec-main/openspec/changes/add-global-install-scope/specs/cli-update/spec.md +0 -34
  49. package/OpenSpec-main/openspec/changes/add-global-install-scope/specs/command-generation/spec.md +0 -22
  50. package/OpenSpec-main/openspec/changes/add-global-install-scope/specs/global-config/spec.md +0 -24
  51. package/OpenSpec-main/openspec/changes/add-global-install-scope/specs/installation-scope/spec.md +0 -71
  52. package/OpenSpec-main/openspec/changes/add-global-install-scope/tasks.md +0 -61
  53. package/OpenSpec-main/openspec/changes/add-qa-smoke-harness/.openspec.yaml +0 -2
  54. package/OpenSpec-main/openspec/changes/add-qa-smoke-harness/proposal.md +0 -45
  55. package/OpenSpec-main/openspec/changes/add-qa-smoke-harness/specs/developer-qa-workflow/spec.md +0 -49
  56. package/OpenSpec-main/openspec/changes/add-tool-command-surface-capabilities/.openspec.yaml +0 -2
  57. package/OpenSpec-main/openspec/changes/add-tool-command-surface-capabilities/proposal.md +0 -111
  58. package/OpenSpec-main/openspec/changes/add-tool-command-surface-capabilities/specs/cli-init/spec.md +0 -121
  59. package/OpenSpec-main/openspec/changes/add-tool-command-surface-capabilities/specs/cli-update/spec.md +0 -48
  60. package/OpenSpec-main/openspec/changes/add-tool-command-surface-capabilities/tasks.md +0 -53
  61. package/OpenSpec-main/openspec/changes/archive/2025-01-11-add-update-command/design.md +0 -86
  62. package/OpenSpec-main/openspec/changes/archive/2025-01-11-add-update-command/proposal.md +0 -29
  63. package/OpenSpec-main/openspec/changes/archive/2025-01-11-add-update-command/specs/cli-update/spec.md +0 -59
  64. package/OpenSpec-main/openspec/changes/archive/2025-01-11-add-update-command/tasks.md +0 -20
  65. package/OpenSpec-main/openspec/changes/archive/2025-01-13-add-list-command/proposal.md +0 -20
  66. package/OpenSpec-main/openspec/changes/archive/2025-01-13-add-list-command/specs/cli-list/spec.md +0 -69
  67. package/OpenSpec-main/openspec/changes/archive/2025-01-13-add-list-command/tasks.md +0 -26
  68. package/OpenSpec-main/openspec/changes/archive/2025-08-05-initialize-typescript-project/design.md +0 -64
  69. package/OpenSpec-main/openspec/changes/archive/2025-08-05-initialize-typescript-project/proposal.md +0 -18
  70. package/OpenSpec-main/openspec/changes/archive/2025-08-05-initialize-typescript-project/tasks.md +0 -25
  71. package/OpenSpec-main/openspec/changes/archive/2025-08-06-add-init-command/design.md +0 -104
  72. package/OpenSpec-main/openspec/changes/archive/2025-08-06-add-init-command/proposal.md +0 -30
  73. package/OpenSpec-main/openspec/changes/archive/2025-08-06-add-init-command/specs/cli-init/spec.md +0 -148
  74. package/OpenSpec-main/openspec/changes/archive/2025-08-06-add-init-command/tasks.md +0 -38
  75. package/OpenSpec-main/openspec/changes/archive/2025-08-06-adopt-future-state-storage/proposal.md +0 -24
  76. package/OpenSpec-main/openspec/changes/archive/2025-08-06-adopt-future-state-storage/specs/openspec-conventions/spec.md +0 -120
  77. package/OpenSpec-main/openspec/changes/archive/2025-08-06-adopt-future-state-storage/tasks.md +0 -38
  78. package/OpenSpec-main/openspec/changes/archive/2025-08-11-add-complexity-guidelines/proposal.md +0 -13
  79. package/OpenSpec-main/openspec/changes/archive/2025-08-11-add-complexity-guidelines/specs/openspec-docs/README.md +0 -472
  80. package/OpenSpec-main/openspec/changes/archive/2025-08-11-add-complexity-guidelines/tasks.md +0 -9
  81. package/OpenSpec-main/openspec/changes/archive/2025-08-13-add-archive-command/proposal.md +0 -15
  82. package/OpenSpec-main/openspec/changes/archive/2025-08-13-add-archive-command/specs/cli-archive/spec.md +0 -111
  83. package/OpenSpec-main/openspec/changes/archive/2025-08-13-add-archive-command/tasks.md +0 -44
  84. package/OpenSpec-main/openspec/changes/archive/2025-08-13-add-diff-command/proposal.md +0 -19
  85. package/OpenSpec-main/openspec/changes/archive/2025-08-13-add-diff-command/specs/cli-diff/spec.md +0 -77
  86. package/OpenSpec-main/openspec/changes/archive/2025-08-13-add-diff-command/tasks.md +0 -23
  87. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-change-commands/design.md +0 -56
  88. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-change-commands/proposal.md +0 -17
  89. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-change-commands/specs/cli-change/spec.md +0 -48
  90. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-change-commands/specs/cli-list/spec.md +0 -12
  91. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-change-commands/tasks.md +0 -34
  92. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-interactive-show-command/proposal.md +0 -20
  93. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-interactive-show-command/specs/cli-change/spec.md +0 -23
  94. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-interactive-show-command/specs/cli-show/spec.md +0 -83
  95. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-interactive-show-command/specs/cli-spec/spec.md +0 -23
  96. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-interactive-show-command/tasks.md +0 -142
  97. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-skip-specs-archive-option/proposal.md +0 -13
  98. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-skip-specs-archive-option/specs/cli-archive/spec.md +0 -191
  99. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-skip-specs-archive-option/tasks.md +0 -57
  100. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-spec-commands/design.md +0 -45
  101. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-spec-commands/proposal.md +0 -19
  102. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-spec-commands/specs/cli-spec/spec.md +0 -43
  103. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-spec-commands/tasks.md +0 -22
  104. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-zod-validation/design.md +0 -104
  105. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-zod-validation/proposal.md +0 -22
  106. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-zod-validation/specs/cli-archive/spec.md +0 -18
  107. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-zod-validation/specs/cli-diff/spec.md +0 -12
  108. package/OpenSpec-main/openspec/changes/archive/2025-08-19-add-zod-validation/tasks.md +0 -59
  109. package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-delta-based-changes/proposal.md +0 -93
  110. package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-delta-based-changes/specs/cli-archive/spec.md +0 -48
  111. package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-delta-based-changes/specs/cli-diff/spec.md +0 -45
  112. package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-delta-based-changes/specs/openspec-conventions/spec.md +0 -101
  113. package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-delta-based-changes/tasks.md +0 -55
  114. package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-verb-noun-cli-structure/design.md +0 -19
  115. package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-verb-noun-cli-structure/proposal.md +0 -67
  116. package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-verb-noun-cli-structure/specs/cli-list/spec.md +0 -57
  117. package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-verb-noun-cli-structure/specs/openspec-conventions/spec.md +0 -23
  118. package/OpenSpec-main/openspec/changes/archive/2025-08-19-adopt-verb-noun-cli-structure/tasks.md +0 -27
  119. package/OpenSpec-main/openspec/changes/archive/2025-08-19-bulk-validation-interactive-selection/proposal.md +0 -20
  120. package/OpenSpec-main/openspec/changes/archive/2025-08-19-bulk-validation-interactive-selection/specs/cli-change/spec.md +0 -22
  121. package/OpenSpec-main/openspec/changes/archive/2025-08-19-bulk-validation-interactive-selection/specs/cli-spec/spec.md +0 -23
  122. package/OpenSpec-main/openspec/changes/archive/2025-08-19-bulk-validation-interactive-selection/specs/cli-validate/spec.md +0 -149
  123. package/OpenSpec-main/openspec/changes/archive/2025-08-19-bulk-validation-interactive-selection/tasks.md +0 -81
  124. package/OpenSpec-main/openspec/changes/archive/2025-08-19-fix-update-tool-selection/proposal.md +0 -40
  125. package/OpenSpec-main/openspec/changes/archive/2025-08-19-fix-update-tool-selection/specs/cli-update/spec.md +0 -23
  126. package/OpenSpec-main/openspec/changes/archive/2025-08-19-fix-update-tool-selection/tasks.md +0 -21
  127. package/OpenSpec-main/openspec/changes/archive/2025-08-19-improve-validate-error-messages/proposal.md +0 -25
  128. package/OpenSpec-main/openspec/changes/archive/2025-08-19-improve-validate-error-messages/specs/cli-validate/spec.md +0 -55
  129. package/OpenSpec-main/openspec/changes/archive/2025-08-19-improve-validate-error-messages/tasks.md +0 -21
  130. package/OpenSpec-main/openspec/changes/archive/2025-08-19-structured-spec-format/proposal.md +0 -36
  131. package/OpenSpec-main/openspec/changes/archive/2025-08-19-structured-spec-format/specs/openspec-conventions/spec.md +0 -192
  132. package/OpenSpec-main/openspec/changes/archive/2025-08-19-structured-spec-format/tasks.md +0 -19
  133. package/OpenSpec-main/openspec/changes/archive/2025-09-12-add-view-dashboard-command/proposal.md +0 -38
  134. package/OpenSpec-main/openspec/changes/archive/2025-09-12-add-view-dashboard-command/specs/cli-view/spec.md +0 -109
  135. package/OpenSpec-main/openspec/changes/archive/2025-09-12-add-view-dashboard-command/tasks.md +0 -47
  136. package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-agents-md-config/proposal.md +0 -28
  137. package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-agents-md-config/specs/cli-init/spec.md +0 -71
  138. package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-agents-md-config/specs/cli-update/spec.md +0 -41
  139. package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-agents-md-config/tasks.md +0 -17
  140. package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-multi-agent-init/proposal.md +0 -35
  141. package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-multi-agent-init/specs/cli-init/spec.md +0 -45
  142. package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-multi-agent-init/tasks.md +0 -16
  143. package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-slash-command-support/proposal.md +0 -119
  144. package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-slash-command-support/specs/cli-init/spec.md +0 -21
  145. package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-slash-command-support/specs/cli-update/spec.md +0 -22
  146. package/OpenSpec-main/openspec/changes/archive/2025-09-29-add-slash-command-support/tasks.md +0 -20
  147. package/OpenSpec-main/openspec/changes/archive/2025-09-29-improve-cli-e2e-plan/proposal.md +0 -19
  148. package/OpenSpec-main/openspec/changes/archive/2025-09-29-improve-cli-e2e-plan/tasks.md +0 -9
  149. package/OpenSpec-main/openspec/changes/archive/2025-09-29-improve-deterministic-tests/proposal.md +0 -78
  150. package/OpenSpec-main/openspec/changes/archive/2025-09-29-improve-deterministic-tests/tasks.md +0 -25
  151. package/OpenSpec-main/openspec/changes/archive/2025-09-29-improve-init-onboarding/proposal.md +0 -13
  152. package/OpenSpec-main/openspec/changes/archive/2025-09-29-improve-init-onboarding/specs/cli-init/spec.md +0 -92
  153. package/OpenSpec-main/openspec/changes/archive/2025-09-29-improve-init-onboarding/tasks.md +0 -12
  154. package/OpenSpec-main/openspec/changes/archive/2025-09-29-remove-diff-command/proposal.md +0 -81
  155. package/OpenSpec-main/openspec/changes/archive/2025-09-29-remove-diff-command/tasks.md +0 -37
  156. package/OpenSpec-main/openspec/changes/archive/2025-09-29-sort-active-changes-by-progress/proposal.md +0 -25
  157. package/OpenSpec-main/openspec/changes/archive/2025-09-29-sort-active-changes-by-progress/specs/cli-view/spec.md +0 -9
  158. package/OpenSpec-main/openspec/changes/archive/2025-09-29-sort-active-changes-by-progress/tasks.md +0 -8
  159. package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-agent-file-name/proposal.md +0 -29
  160. package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-agent-file-name/specs/cli-init/spec.md +0 -40
  161. package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-agent-file-name/specs/cli-update/spec.md +0 -22
  162. package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-agent-file-name/specs/openspec-conventions/spec.md +0 -27
  163. package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-agent-file-name/tasks.md +0 -22
  164. package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-agent-instructions/design.md +0 -130
  165. package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-agent-instructions/proposal.md +0 -117
  166. package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-agent-instructions/tasks.md +0 -69
  167. package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-markdown-parser-crlf/proposal.md +0 -19
  168. package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-markdown-parser-crlf/specs/cli-validate/spec.md +0 -9
  169. package/OpenSpec-main/openspec/changes/archive/2025-09-29-update-markdown-parser-crlf/tasks.md +0 -11
  170. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-codex-slash-command-support/proposal.md +0 -25
  171. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-codex-slash-command-support/specs/cli-init/spec.md +0 -56
  172. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-codex-slash-command-support/specs/cli-update/spec.md +0 -41
  173. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-codex-slash-command-support/tasks.md +0 -19
  174. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-github-copilot-prompts/proposal.md +0 -25
  175. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-github-copilot-prompts/specs/cli-init/spec.md +0 -48
  176. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-github-copilot-prompts/specs/cli-update/spec.md +0 -48
  177. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-github-copilot-prompts/tasks.md +0 -30
  178. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-kilocode-workflows/proposal.md +0 -17
  179. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-kilocode-workflows/specs/cli-init/spec.md +0 -43
  180. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-kilocode-workflows/specs/cli-update/spec.md +0 -27
  181. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-kilocode-workflows/tasks.md +0 -15
  182. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-non-interactive-init-options/proposal.md +0 -12
  183. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-non-interactive-init-options/specs/cli-init/spec.md +0 -39
  184. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-non-interactive-init-options/tasks.md +0 -17
  185. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-windsurf-workflows/proposal.md +0 -17
  186. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-windsurf-workflows/specs/cli-init/spec.md +0 -42
  187. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-windsurf-workflows/specs/cli-update/spec.md +0 -27
  188. package/OpenSpec-main/openspec/changes/archive/2025-10-14-add-windsurf-workflows/tasks.md +0 -17
  189. package/OpenSpec-main/openspec/changes/archive/2025-10-14-enhance-validation-error-messages/proposal.md +0 -12
  190. package/OpenSpec-main/openspec/changes/archive/2025-10-14-enhance-validation-error-messages/specs/cli-validate/spec.md +0 -39
  191. package/OpenSpec-main/openspec/changes/archive/2025-10-14-enhance-validation-error-messages/tasks.md +0 -12
  192. package/OpenSpec-main/openspec/changes/archive/2025-10-14-improve-agent-instruction-usability/proposal.md +0 -12
  193. package/OpenSpec-main/openspec/changes/archive/2025-10-14-improve-agent-instruction-usability/specs/docs-agent-instructions/spec.md +0 -33
  194. package/OpenSpec-main/openspec/changes/archive/2025-10-14-improve-agent-instruction-usability/tasks.md +0 -11
  195. package/OpenSpec-main/openspec/changes/archive/2025-10-14-slim-root-agents-file/proposal.md +0 -13
  196. package/OpenSpec-main/openspec/changes/archive/2025-10-14-slim-root-agents-file/tasks.md +0 -15
  197. package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-cli-init-enter-selection/proposal.md +0 -14
  198. package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-cli-init-enter-selection/specs/cli-init/spec.md +0 -10
  199. package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-cli-init-enter-selection/tasks.md +0 -8
  200. package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-cli-init-root-agents/proposal.md +0 -15
  201. package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-cli-init-root-agents/specs/cli-init/spec.md +0 -32
  202. package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-cli-init-root-agents/specs/cli-update/spec.md +0 -10
  203. package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-cli-init-root-agents/tasks.md +0 -11
  204. package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-release-automation/proposal.md +0 -49
  205. package/OpenSpec-main/openspec/changes/archive/2025-10-14-update-release-automation/tasks.md +0 -12
  206. package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-archive-command-arguments/proposal.md +0 -17
  207. package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-archive-command-arguments/specs/cli-update/spec.md +0 -32
  208. package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-archive-command-arguments/tasks.md +0 -15
  209. package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-cline-support/proposal.md +0 -15
  210. package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-cline-support/specs/cli-init/spec.md +0 -97
  211. package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-cline-support/tasks.md +0 -19
  212. package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-crush-support/proposal.md +0 -13
  213. package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-crush-support/specs/cli-init/spec.md +0 -67
  214. package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-crush-support/tasks.md +0 -7
  215. package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-factory-slash-commands/proposal.md +0 -12
  216. package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-factory-slash-commands/specs/cli-init/spec.md +0 -54
  217. package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-factory-slash-commands/specs/cli-update/spec.md +0 -54
  218. package/OpenSpec-main/openspec/changes/archive/2025-10-22-add-factory-slash-commands/tasks.md +0 -11
  219. package/OpenSpec-main/openspec/changes/archive/2025-11-06-add-shell-completions/design.md +0 -525
  220. package/OpenSpec-main/openspec/changes/archive/2025-11-06-add-shell-completions/proposal.md +0 -29
  221. package/OpenSpec-main/openspec/changes/archive/2025-11-06-add-shell-completions/specs/cli-completion/spec.md +0 -300
  222. package/OpenSpec-main/openspec/changes/archive/2025-11-06-add-shell-completions/tasks.md +0 -81
  223. package/OpenSpec-main/openspec/changes/archive/2025-12-20-add-global-config-dir/design.md +0 -105
  224. package/OpenSpec-main/openspec/changes/archive/2025-12-20-add-global-config-dir/proposal.md +0 -20
  225. package/OpenSpec-main/openspec/changes/archive/2025-12-20-add-global-config-dir/specs/global-config/spec.md +0 -76
  226. package/OpenSpec-main/openspec/changes/archive/2025-12-20-add-global-config-dir/tasks.md +0 -26
  227. package/OpenSpec-main/openspec/changes/archive/2025-12-21-add-config-command/design.md +0 -89
  228. package/OpenSpec-main/openspec/changes/archive/2025-12-21-add-config-command/proposal.md +0 -60
  229. package/OpenSpec-main/openspec/changes/archive/2025-12-21-add-config-command/specs/cli-config/spec.md +0 -213
  230. package/OpenSpec-main/openspec/changes/archive/2025-12-21-add-config-command/tasks.md +0 -28
  231. package/OpenSpec-main/openspec/changes/archive/2025-12-23-extend-shell-completions/proposal.md +0 -15
  232. package/OpenSpec-main/openspec/changes/archive/2025-12-23-extend-shell-completions/specs/cli-completion/spec.md +0 -328
  233. package/OpenSpec-main/openspec/changes/archive/2025-12-23-extend-shell-completions/tasks.md +0 -49
  234. package/OpenSpec-main/openspec/changes/archive/2025-12-24-add-artifact-graph-core/design.md +0 -197
  235. package/OpenSpec-main/openspec/changes/archive/2025-12-24-add-artifact-graph-core/proposal.md +0 -18
  236. package/OpenSpec-main/openspec/changes/archive/2025-12-24-add-artifact-graph-core/specs/artifact-graph/spec.md +0 -103
  237. package/OpenSpec-main/openspec/changes/archive/2025-12-24-add-artifact-graph-core/tasks.md +0 -61
  238. package/OpenSpec-main/openspec/changes/archive/2025-12-25-add-change-manager/design.md +0 -74
  239. package/OpenSpec-main/openspec/changes/archive/2025-12-25-add-change-manager/proposal.md +0 -45
  240. package/OpenSpec-main/openspec/changes/archive/2025-12-25-add-change-manager/specs/change-creation/spec.md +0 -63
  241. package/OpenSpec-main/openspec/changes/archive/2025-12-25-add-change-manager/tasks.md +0 -30
  242. package/OpenSpec-main/openspec/changes/archive/2025-12-28-add-artifact-workflow-cli/design.md +0 -112
  243. package/OpenSpec-main/openspec/changes/archive/2025-12-28-add-artifact-workflow-cli/proposal.md +0 -33
  244. package/OpenSpec-main/openspec/changes/archive/2025-12-28-add-artifact-workflow-cli/specs/cli-artifact-workflow/spec.md +0 -153
  245. package/OpenSpec-main/openspec/changes/archive/2025-12-28-add-artifact-workflow-cli/tasks.md +0 -48
  246. package/OpenSpec-main/openspec/changes/archive/2025-12-28-add-instruction-loader/design.md +0 -149
  247. package/OpenSpec-main/openspec/changes/archive/2025-12-28-add-instruction-loader/proposal.md +0 -20
  248. package/OpenSpec-main/openspec/changes/archive/2025-12-28-add-instruction-loader/specs/instruction-loader/spec.md +0 -70
  249. package/OpenSpec-main/openspec/changes/archive/2025-12-28-add-instruction-loader/tasks.md +0 -13
  250. package/OpenSpec-main/openspec/changes/archive/2025-12-28-restructure-schema-directories/design.md +0 -129
  251. package/OpenSpec-main/openspec/changes/archive/2025-12-28-restructure-schema-directories/proposal.md +0 -20
  252. package/OpenSpec-main/openspec/changes/archive/2025-12-28-restructure-schema-directories/specs/artifact-graph/spec.md +0 -49
  253. package/OpenSpec-main/openspec/changes/archive/2025-12-28-restructure-schema-directories/tasks.md +0 -32
  254. package/OpenSpec-main/openspec/changes/archive/2025-12-29-unify-change-state-model/design.md +0 -151
  255. package/OpenSpec-main/openspec/changes/archive/2025-12-29-unify-change-state-model/proposal.md +0 -101
  256. package/OpenSpec-main/openspec/changes/archive/2025-12-29-unify-change-state-model/specs/cli-artifact-workflow/spec.md +0 -109
  257. package/OpenSpec-main/openspec/changes/archive/2025-12-29-unify-change-state-model/specs/cli-view/spec.md +0 -60
  258. package/OpenSpec-main/openspec/changes/archive/2025-12-29-unify-change-state-model/tasks.md +0 -25
  259. package/OpenSpec-main/openspec/changes/archive/2025-12-30-add-antigravity-support/proposal.md +0 -11
  260. package/OpenSpec-main/openspec/changes/archive/2025-12-30-add-antigravity-support/specs/cli-init/spec.md +0 -105
  261. package/OpenSpec-main/openspec/changes/archive/2025-12-30-add-antigravity-support/specs/cli-update/spec.md +0 -92
  262. package/OpenSpec-main/openspec/changes/archive/2025-12-30-add-antigravity-support/tasks.md +0 -12
  263. package/OpenSpec-main/openspec/changes/archive/2025-12-30-fix-cline-workflows-implementation/proposal.md +0 -13
  264. package/OpenSpec-main/openspec/changes/archive/2025-12-30-fix-cline-workflows-implementation/specs/cli-init/spec.md +0 -105
  265. package/OpenSpec-main/openspec/changes/archive/2025-12-30-fix-cline-workflows-implementation/specs/cli-update/spec.md +0 -92
  266. package/OpenSpec-main/openspec/changes/archive/2025-12-30-fix-cline-workflows-implementation/tasks.md +0 -13
  267. package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-agent-schema-selection/proposal.md +0 -26
  268. package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-agent-schema-selection/tasks.md +0 -32
  269. package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-per-change-schema-metadata/design.md +0 -147
  270. package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-per-change-schema-metadata/proposal.md +0 -29
  271. package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-per-change-schema-metadata/specs/cli-artifact-workflow/spec.md +0 -98
  272. package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-per-change-schema-metadata/tasks.md +0 -29
  273. package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-specs-apply-command/.openspec.yaml +0 -2
  274. package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-specs-apply-command/design.md +0 -77
  275. package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-specs-apply-command/proposal.md +0 -32
  276. package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-specs-apply-command/specs/specs-sync-skill/spec.md +0 -67
  277. package/OpenSpec-main/openspec/changes/archive/2026-01-06-add-specs-apply-command/tasks.md +0 -40
  278. package/OpenSpec-main/openspec/changes/archive/2026-01-06-make-apply-instructions-schema-aware/proposal.md +0 -138
  279. package/OpenSpec-main/openspec/changes/archive/2026-01-06-make-apply-instructions-schema-aware/specs/cli-artifact-workflow/spec.md +0 -60
  280. package/OpenSpec-main/openspec/changes/archive/2026-01-06-make-apply-instructions-schema-aware/tasks.md +0 -35
  281. package/OpenSpec-main/openspec/changes/archive/2026-01-06-opsx-archive-command/.openspec.yaml +0 -2
  282. package/OpenSpec-main/openspec/changes/archive/2026-01-06-opsx-archive-command/design.md +0 -84
  283. package/OpenSpec-main/openspec/changes/archive/2026-01-06-opsx-archive-command/proposal.md +0 -28
  284. package/OpenSpec-main/openspec/changes/archive/2026-01-06-opsx-archive-command/specs/opsx-archive-skill/spec.md +0 -122
  285. package/OpenSpec-main/openspec/changes/archive/2026-01-06-opsx-archive-command/tasks.md +0 -23
  286. package/OpenSpec-main/openspec/changes/archive/2026-01-07-add-nix-flake-support/.openspec.yaml +0 -2
  287. package/OpenSpec-main/openspec/changes/archive/2026-01-07-add-nix-flake-support/design.md +0 -94
  288. package/OpenSpec-main/openspec/changes/archive/2026-01-07-add-nix-flake-support/proposal.md +0 -25
  289. package/OpenSpec-main/openspec/changes/archive/2026-01-07-add-nix-flake-support/specs/nix-flake-support/spec.md +0 -79
  290. package/OpenSpec-main/openspec/changes/archive/2026-01-07-add-nix-flake-support/tasks.md +0 -65
  291. package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-flake-update-script/.openspec.yaml +0 -2
  292. package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-flake-update-script/design.md +0 -117
  293. package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-flake-update-script/proposal.md +0 -23
  294. package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-flake-update-script/specs/flake-update-script/spec.md +0 -93
  295. package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-flake-update-script/tasks.md +0 -55
  296. package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-posthog-analytics/.openspec.yaml +0 -2
  297. package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-posthog-analytics/design.md +0 -175
  298. package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-posthog-analytics/proposal.md +0 -37
  299. package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-posthog-analytics/specs/global-config/spec.md +0 -21
  300. package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-posthog-analytics/specs/telemetry/spec.md +0 -116
  301. package/OpenSpec-main/openspec/changes/archive/2026-01-09-add-posthog-analytics/tasks.md +0 -47
  302. package/OpenSpec-main/openspec/changes/archive/2026-01-09-fix-codebuddy-frontmatter-fields/proposal.md +0 -16
  303. package/OpenSpec-main/openspec/changes/archive/2026-01-09-fix-codebuddy-frontmatter-fields/specs/cli-init/spec.md +0 -75
  304. package/OpenSpec-main/openspec/changes/archive/2026-01-09-fix-codebuddy-frontmatter-fields/specs/cli-update/spec.md +0 -56
  305. package/OpenSpec-main/openspec/changes/archive/2026-01-09-fix-codebuddy-frontmatter-fields/tasks.md +0 -6
  306. package/OpenSpec-main/openspec/changes/archive/2026-01-15-add-nix-ci-validation/design.md +0 -206
  307. package/OpenSpec-main/openspec/changes/archive/2026-01-15-add-nix-ci-validation/proposal.md +0 -21
  308. package/OpenSpec-main/openspec/changes/archive/2026-01-15-add-nix-ci-validation/specs/ci-nix-validation/spec.md +0 -104
  309. package/OpenSpec-main/openspec/changes/archive/2026-01-15-add-nix-ci-validation/tasks.md +0 -49
  310. package/OpenSpec-main/openspec/changes/archive/2026-01-30-opencode-command-references/.openspec.yaml +0 -2
  311. package/OpenSpec-main/openspec/changes/archive/2026-01-30-opencode-command-references/README.md +0 -3
  312. package/OpenSpec-main/openspec/changes/archive/2026-01-30-opencode-command-references/design.md +0 -70
  313. package/OpenSpec-main/openspec/changes/archive/2026-01-30-opencode-command-references/proposal.md +0 -32
  314. package/OpenSpec-main/openspec/changes/archive/2026-01-30-opencode-command-references/specs/no-changes.md +0 -9
  315. package/OpenSpec-main/openspec/changes/archive/2026-01-30-opencode-command-references/tasks.md +0 -22
  316. package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-feedback-command/proposal.md +0 -20
  317. package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-feedback-command/specs/cli-feedback/spec.md +0 -188
  318. package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-feedback-command/tasks.md +0 -30
  319. package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-opsx-onboard-skill/.openspec.yaml +0 -2
  320. package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-opsx-onboard-skill/design.md +0 -115
  321. package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-opsx-onboard-skill/proposal.md +0 -27
  322. package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-opsx-onboard-skill/specs/opsx-onboard-skill/spec.md +0 -162
  323. package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-opsx-onboard-skill/tasks.md +0 -21
  324. package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-verify-skill/design.md +0 -96
  325. package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-verify-skill/proposal.md +0 -48
  326. package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-verify-skill/specs/opsx-verify-skill/spec.md +0 -190
  327. package/OpenSpec-main/openspec/changes/archive/2026-02-17-add-verify-skill/tasks.md +0 -15
  328. package/OpenSpec-main/openspec/changes/archive/2026-02-17-merge-init-experimental/.openspec.yaml +0 -2
  329. package/OpenSpec-main/openspec/changes/archive/2026-02-17-merge-init-experimental/design.md +0 -193
  330. package/OpenSpec-main/openspec/changes/archive/2026-02-17-merge-init-experimental/proposal.md +0 -32
  331. package/OpenSpec-main/openspec/changes/archive/2026-02-17-merge-init-experimental/specs/cli-init/spec.md +0 -176
  332. package/OpenSpec-main/openspec/changes/archive/2026-02-17-merge-init-experimental/specs/legacy-cleanup/spec.md +0 -158
  333. package/OpenSpec-main/openspec/changes/archive/2026-02-17-merge-init-experimental/tasks.md +0 -67
  334. package/OpenSpec-main/openspec/changes/archive/2026-02-17-multi-provider-skill-generation/.openspec.yaml +0 -2
  335. package/OpenSpec-main/openspec/changes/archive/2026-02-17-multi-provider-skill-generation/design.md +0 -144
  336. package/OpenSpec-main/openspec/changes/archive/2026-02-17-multi-provider-skill-generation/proposal.md +0 -36
  337. package/OpenSpec-main/openspec/changes/archive/2026-02-17-multi-provider-skill-generation/specs/ai-tool-paths/spec.md +0 -63
  338. package/OpenSpec-main/openspec/changes/archive/2026-02-17-multi-provider-skill-generation/specs/cli-artifact-workflow/spec.md +0 -60
  339. package/OpenSpec-main/openspec/changes/archive/2026-02-17-multi-provider-skill-generation/specs/command-generation/spec.md +0 -98
  340. package/OpenSpec-main/openspec/changes/archive/2026-02-17-multi-provider-skill-generation/tasks.md +0 -55
  341. package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-config/.openspec.yaml +0 -2
  342. package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-config/design.md +0 -665
  343. package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-config/proposal.md +0 -774
  344. package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-config/specs/config-loading/spec.md +0 -119
  345. package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-config/specs/context-injection/spec.md +0 -51
  346. package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-config/specs/rules-injection/spec.md +0 -99
  347. package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-config/specs/schema-resolution/spec.md +0 -83
  348. package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-config/tasks.md +0 -72
  349. package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-local-schemas/.openspec.yaml +0 -2
  350. package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-local-schemas/design.md +0 -117
  351. package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-local-schemas/proposal.md +0 -167
  352. package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-local-schemas/specs/schema-resolution/spec.md +0 -88
  353. package/OpenSpec-main/openspec/changes/archive/2026-02-17-project-local-schemas/tasks.md +0 -28
  354. package/OpenSpec-main/openspec/changes/archive/2026-02-17-schema-management-cli/.openspec.yaml +0 -2
  355. package/OpenSpec-main/openspec/changes/archive/2026-02-17-schema-management-cli/design.md +0 -113
  356. package/OpenSpec-main/openspec/changes/archive/2026-02-17-schema-management-cli/proposal.md +0 -55
  357. package/OpenSpec-main/openspec/changes/archive/2026-02-17-schema-management-cli/specs/schema-fork-command/spec.md +0 -66
  358. package/OpenSpec-main/openspec/changes/archive/2026-02-17-schema-management-cli/specs/schema-init-command/spec.md +0 -71
  359. package/OpenSpec-main/openspec/changes/archive/2026-02-17-schema-management-cli/specs/schema-validate-command/spec.md +0 -86
  360. package/OpenSpec-main/openspec/changes/archive/2026-02-17-schema-management-cli/specs/schema-which-command/spec.md +0 -65
  361. package/OpenSpec-main/openspec/changes/archive/2026-02-17-schema-management-cli/tasks.md +0 -67
  362. package/OpenSpec-main/openspec/changes/archive/2026-04-23-add-kimi-cli-skills-only-support/.openspec.yaml +0 -2
  363. package/OpenSpec-main/openspec/changes/archive/2026-04-23-add-kimi-cli-skills-only-support/README.md +0 -3
  364. package/OpenSpec-main/openspec/changes/archive/2026-04-23-add-kimi-cli-skills-only-support/design.md +0 -85
  365. package/OpenSpec-main/openspec/changes/archive/2026-04-23-add-kimi-cli-skills-only-support/proposal.md +0 -38
  366. package/OpenSpec-main/openspec/changes/archive/2026-04-23-add-kimi-cli-skills-only-support/specs/ai-tool-paths/spec.md +0 -12
  367. package/OpenSpec-main/openspec/changes/archive/2026-04-23-add-kimi-cli-skills-only-support/specs/cli-init/spec.md +0 -37
  368. package/OpenSpec-main/openspec/changes/archive/2026-04-23-add-kimi-cli-skills-only-support/tasks.md +0 -22
  369. package/OpenSpec-main/openspec/changes/archive/2026-05-04-workspace-foundation/design.md +0 -208
  370. package/OpenSpec-main/openspec/changes/archive/2026-05-04-workspace-foundation/proposal.md +0 -142
  371. package/OpenSpec-main/openspec/changes/archive/2026-05-04-workspace-foundation/specs/openspec-conventions/spec.md +0 -29
  372. package/OpenSpec-main/openspec/changes/archive/2026-05-04-workspace-foundation/specs/workspace-foundation/spec.md +0 -199
  373. package/OpenSpec-main/openspec/changes/archive/2026-05-04-workspace-foundation/tasks.md +0 -56
  374. package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-create-and-register-repos/design.md +0 -356
  375. package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-create-and-register-repos/proposal.md +0 -128
  376. package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-create-and-register-repos/specs/cli-artifact-workflow/spec.md +0 -24
  377. package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-create-and-register-repos/specs/workspace-foundation/spec.md +0 -35
  378. package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-create-and-register-repos/specs/workspace-links/spec.md +0 -356
  379. package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-create-and-register-repos/tasks.md +0 -121
  380. package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-open-agent-context/design.md +0 -266
  381. package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-open-agent-context/proposal.md +0 -65
  382. package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-open-agent-context/specs/workspace-foundation/spec.md +0 -76
  383. package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-open-agent-context/specs/workspace-open/spec.md +0 -199
  384. package/OpenSpec-main/openspec/changes/archive/2026-05-06-workspace-open-agent-context/tasks.md +0 -89
  385. package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/design.md +0 -242
  386. package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/proposal.md +0 -78
  387. package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/artifact-graph/spec.md +0 -36
  388. package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/change-creation/spec.md +0 -42
  389. package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/cli-artifact-workflow/spec.md +0 -100
  390. package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/cli-config/spec.md +0 -55
  391. package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/cli-update/spec.md +0 -21
  392. package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/openspec-conventions/spec.md +0 -32
  393. package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/schema-resolution/spec.md +0 -25
  394. package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/workspace-change-planning/spec.md +0 -67
  395. package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/specs/workspace-links/spec.md +0 -163
  396. package/OpenSpec-main/openspec/changes/archive/2026-05-14-workspace-change-planning/tasks.md +0 -133
  397. package/OpenSpec-main/openspec/changes/fix-opencode-commands-directory/.openspec.yaml +0 -2
  398. package/OpenSpec-main/openspec/changes/fix-opencode-commands-directory/design.md +0 -48
  399. package/OpenSpec-main/openspec/changes/fix-opencode-commands-directory/proposal.md +0 -26
  400. package/OpenSpec-main/openspec/changes/fix-opencode-commands-directory/specs/command-generation/spec.md +0 -63
  401. package/OpenSpec-main/openspec/changes/fix-opencode-commands-directory/tasks.md +0 -19
  402. package/OpenSpec-main/openspec/changes/graceful-status-no-changes/.openspec.yaml +0 -2
  403. package/OpenSpec-main/openspec/changes/graceful-status-no-changes/design.md +0 -38
  404. package/OpenSpec-main/openspec/changes/graceful-status-no-changes/proposal.md +0 -25
  405. package/OpenSpec-main/openspec/changes/graceful-status-no-changes/specs/graceful-status-empty/spec.md +0 -27
  406. package/OpenSpec-main/openspec/changes/graceful-status-no-changes/tasks.md +0 -16
  407. package/OpenSpec-main/openspec/changes/schema-alias-support/.openspec.yaml +0 -2
  408. package/OpenSpec-main/openspec/changes/schema-alias-support/proposal.md +0 -28
  409. package/OpenSpec-main/openspec/changes/simplify-skill-installation/.openspec.yaml +0 -2
  410. package/OpenSpec-main/openspec/changes/simplify-skill-installation/design.md +0 -288
  411. package/OpenSpec-main/openspec/changes/simplify-skill-installation/proposal.md +0 -202
  412. package/OpenSpec-main/openspec/changes/simplify-skill-installation/specs/cli-init/spec.md +0 -199
  413. package/OpenSpec-main/openspec/changes/simplify-skill-installation/specs/cli-update/spec.md +0 -177
  414. package/OpenSpec-main/openspec/changes/simplify-skill-installation/specs/profiles/spec.md +0 -142
  415. package/OpenSpec-main/openspec/changes/simplify-skill-installation/specs/propose-workflow/spec.md +0 -42
  416. package/OpenSpec-main/openspec/changes/simplify-skill-installation/tasks.md +0 -132
  417. package/OpenSpec-main/openspec/changes/unify-template-generation-pipeline/.openspec.yaml +0 -2
  418. package/OpenSpec-main/openspec/changes/unify-template-generation-pipeline/design.md +0 -149
  419. package/OpenSpec-main/openspec/changes/unify-template-generation-pipeline/proposal.md +0 -47
  420. package/OpenSpec-main/openspec/changes/unify-template-generation-pipeline/specs/template-artifact-pipeline/spec.md +0 -89
  421. package/OpenSpec-main/openspec/changes/unify-template-generation-pipeline/tasks.md +0 -41
  422. package/OpenSpec-main/openspec/changes/workspace-agent-guidance/.openspec.yaml +0 -2
  423. package/OpenSpec-main/openspec/changes/workspace-agent-guidance/proposal.md +0 -100
  424. package/OpenSpec-main/openspec/changes/workspace-apply-repo-slice/proposal.md +0 -58
  425. package/OpenSpec-main/openspec/changes/workspace-reimplementation-roadmap/HISTORICAL_DIRECTION.md +0 -511
  426. package/OpenSpec-main/openspec/changes/workspace-reimplementation-roadmap/POC_REFERENCE_GUIDE.md +0 -266
  427. package/OpenSpec-main/openspec/changes/workspace-reimplementation-roadmap/README.md +0 -107
  428. package/OpenSpec-main/openspec/changes/workspace-reimplementation-roadmap/START_HERE.md +0 -105
  429. package/OpenSpec-main/openspec/changes/workspace-reimplementation-roadmap/proposal.md +0 -62
  430. package/OpenSpec-main/openspec/changes/workspace-verify-and-archive/proposal.md +0 -57
  431. package/OpenSpec-main/openspec/config.yaml +0 -36
  432. package/OpenSpec-main/openspec/explorations/explore-workflow-ux.md +0 -116
  433. package/OpenSpec-main/openspec/explorations/workspace-architecture.md +0 -857
  434. package/OpenSpec-main/openspec/explorations/workspace-roadmap.md +0 -367
  435. package/OpenSpec-main/openspec/explorations/workspace-user-journeys.md +0 -2259
  436. package/OpenSpec-main/openspec/explorations/workspace-ux-simplification.md +0 -491
  437. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/.initiative.yaml +0 -27
  438. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/README.md +0 -33
  439. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/decisions.md +0 -204
  440. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/direction.md +0 -447
  441. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/questions.md +0 -23
  442. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/roadmap.md +0 -759
  443. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/tasks.md +0 -308
  444. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/01-lock-the-direction/evidence.md +0 -154
  445. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/01-lock-the-direction/plan.md +0 -90
  446. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/01-lock-the-direction/tasks.md +0 -44
  447. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/02-stabilize-workspace-as-local-view/evidence.md +0 -68
  448. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/02-stabilize-workspace-as-local-view/plan.md +0 -80
  449. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/02-stabilize-workspace-as-local-view/tasks.md +0 -23
  450. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/03-add-context-store-foundation/evidence.md +0 -43
  451. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/03-add-context-store-foundation/plan.md +0 -85
  452. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/03-add-context-store-foundation/tasks.md +0 -17
  453. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/04-add-collection-foundation/evidence.md +0 -77
  454. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/04-add-collection-foundation/plan.md +0 -198
  455. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/04-add-collection-foundation/tasks.md +0 -14
  456. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/05-ship-initiative-mvp/evidence.md +0 -99
  457. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/05-ship-initiative-mvp/plan.md +0 -236
  458. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/05-ship-initiative-mvp/tasks.md +0 -21
  459. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/06-add-minimal-context-store-ux/evidence.md +0 -97
  460. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/06-add-minimal-context-store-ux/plan.md +0 -333
  461. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/06-add-minimal-context-store-ux/tasks.md +0 -29
  462. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/07-add-agent-first-initiative-discovery/evidence.md +0 -97
  463. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/07-add-agent-first-initiative-discovery/plan.md +0 -184
  464. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/07-add-agent-first-initiative-discovery/tasks.md +0 -27
  465. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/08-connect-repo-local-changes-to-initiatives/evidence.md +0 -239
  466. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/08-connect-repo-local-changes-to-initiatives/plan.md +0 -279
  467. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/08-connect-repo-local-changes-to-initiatives/tasks.md +0 -22
  468. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/09-add-initiative-resolve/decision-review.md +0 -64
  469. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/09-add-initiative-resolve/evidence.md +0 -106
  470. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/09-add-initiative-resolve/plan.md +0 -141
  471. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/09-add-initiative-resolve/tasks.md +0 -22
  472. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/10-let-workspaces-open-initiatives/plan.md +0 -430
  473. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/10-let-workspaces-open-initiatives/tasks.md +0 -43
  474. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/11-manual-beta-reality-pass/notes.md +0 -289
  475. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/11-manual-beta-reality-pass/plan.md +0 -39
  476. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/11-manual-beta-reality-pass/tasks.md +0 -8
  477. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/12-context-store-first-run-and-cleanup-ux/evidence.md +0 -45
  478. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/12-context-store-first-run-and-cleanup-ux/plan.md +0 -150
  479. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/12-context-store-first-run-and-cleanup-ux/tasks.md +0 -23
  480. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/13-agent-handoff-output-and-delivery-polish/evidence.md +0 -25
  481. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/13-agent-handoff-output-and-delivery-polish/plan.md +0 -98
  482. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/13-agent-handoff-output-and-delivery-polish/tasks.md +0 -25
  483. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/14-workspaces-beta-guide-split/plan.md +0 -37
  484. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/14-workspaces-beta-guide-split/tasks.md +0 -9
  485. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/15-context-store-project-roots-and-schema-led-initiatives/evidence.md +0 -140
  486. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/15-context-store-project-roots-and-schema-led-initiatives/plan.md +0 -344
  487. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/15-context-store-project-roots-and-schema-led-initiatives/tasks.md +0 -39
  488. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/16-add-escalation-ux/plan.md +0 -26
  489. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/16-add-escalation-ux/tasks.md +0 -7
  490. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/17-harden-team-shared-coordination/plan.md +0 -25
  491. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/17-harden-team-shared-coordination/tasks.md +0 -7
  492. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/18-explore-initiative-hosted-target-bound-change-artifacts/evidence.md +0 -397
  493. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/18-explore-initiative-hosted-target-bound-change-artifacts/plan.md +0 -180
  494. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/18-explore-initiative-hosted-target-bound-change-artifacts/tasks.md +0 -28
  495. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/19-review-workspace-beta-compatibility-before-public-release/plan.md +0 -62
  496. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/19-review-workspace-beta-compatibility-before-public-release/tasks.md +0 -16
  497. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/proposed-initiative-next-agent-handoff-ux/evidence.md +0 -47
  498. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/proposed-initiative-next-agent-handoff-ux/plan.md +0 -90
  499. package/OpenSpec-main/openspec/initiatives/context-store-and-initiatives/work-items/proposed-initiative-next-agent-handoff-ux/tasks.md +0 -18
  500. package/OpenSpec-main/openspec/specs/ai-tool-paths/spec.md +0 -63
  501. package/OpenSpec-main/openspec/specs/artifact-graph/spec.md +0 -165
  502. package/OpenSpec-main/openspec/specs/change-creation/spec.md +0 -108
  503. package/OpenSpec-main/openspec/specs/ci-nix-validation/spec.md +0 -107
  504. package/OpenSpec-main/openspec/specs/cli-archive/spec.md +0 -210
  505. package/OpenSpec-main/openspec/specs/cli-artifact-workflow/spec.md +0 -398
  506. package/OpenSpec-main/openspec/specs/cli-change/spec.md +0 -92
  507. package/OpenSpec-main/openspec/specs/cli-completion/spec.md +0 -432
  508. package/OpenSpec-main/openspec/specs/cli-config/spec.md +0 -318
  509. package/OpenSpec-main/openspec/specs/cli-feedback/spec.md +0 -193
  510. package/OpenSpec-main/openspec/specs/cli-init/spec.md +0 -269
  511. package/OpenSpec-main/openspec/specs/cli-list/spec.md +0 -103
  512. package/OpenSpec-main/openspec/specs/cli-show/spec.md +0 -86
  513. package/OpenSpec-main/openspec/specs/cli-spec/spec.md +0 -88
  514. package/OpenSpec-main/openspec/specs/cli-update/spec.md +0 -229
  515. package/OpenSpec-main/openspec/specs/cli-validate/spec.md +0 -219
  516. package/OpenSpec-main/openspec/specs/cli-view/spec.md +0 -129
  517. package/OpenSpec-main/openspec/specs/command-generation/spec.md +0 -97
  518. package/OpenSpec-main/openspec/specs/config-loading/spec.md +0 -122
  519. package/OpenSpec-main/openspec/specs/context-injection/spec.md +0 -53
  520. package/OpenSpec-main/openspec/specs/docs-agent-instructions/spec.md +0 -62
  521. package/OpenSpec-main/openspec/specs/global-config/spec.md +0 -101
  522. package/OpenSpec-main/openspec/specs/instruction-loader/spec.md +0 -70
  523. package/OpenSpec-main/openspec/specs/legacy-cleanup/spec.md +0 -163
  524. package/OpenSpec-main/openspec/specs/openspec-conventions/spec.md +0 -556
  525. package/OpenSpec-main/openspec/specs/opsx-archive-skill/spec.md +0 -128
  526. package/OpenSpec-main/openspec/specs/opsx-onboard-skill/spec.md +0 -167
  527. package/OpenSpec-main/openspec/specs/opsx-verify-skill/spec.md +0 -189
  528. package/OpenSpec-main/openspec/specs/rules-injection/spec.md +0 -102
  529. package/OpenSpec-main/openspec/specs/schema-fork-command/spec.md +0 -71
  530. package/OpenSpec-main/openspec/specs/schema-init-command/spec.md +0 -76
  531. package/OpenSpec-main/openspec/specs/schema-resolution/spec.md +0 -201
  532. package/OpenSpec-main/openspec/specs/schema-validate-command/spec.md +0 -91
  533. package/OpenSpec-main/openspec/specs/schema-which-command/spec.md +0 -70
  534. package/OpenSpec-main/openspec/specs/specs-sync-skill/spec.md +0 -72
  535. package/OpenSpec-main/openspec/specs/telemetry/spec.md +0 -122
  536. package/OpenSpec-main/openspec/specs/workspace-change-planning/spec.md +0 -71
  537. package/OpenSpec-main/openspec/specs/workspace-foundation/spec.md +0 -279
  538. package/OpenSpec-main/openspec/specs/workspace-links/spec.md +0 -529
  539. package/OpenSpec-main/openspec/specs/workspace-open/spec.md +0 -205
  540. package/OpenSpec-main/openspec-parallel-merge-plan.md +0 -98
  541. package/OpenSpec-main/package-lock.json +0 -4978
  542. package/OpenSpec-main/package.json +0 -84
  543. package/OpenSpec-main/pnpm-lock.yaml +0 -3187
  544. package/OpenSpec-main/schemas/spec-driven/schema.yaml +0 -153
  545. package/OpenSpec-main/schemas/spec-driven/templates/design.md +0 -19
  546. package/OpenSpec-main/schemas/spec-driven/templates/proposal.md +0 -23
  547. package/OpenSpec-main/schemas/spec-driven/templates/spec.md +0 -8
  548. package/OpenSpec-main/schemas/spec-driven/templates/tasks.md +0 -9
  549. package/OpenSpec-main/schemas/workspace-planning/schema.yaml +0 -72
  550. package/OpenSpec-main/schemas/workspace-planning/templates/design.md +0 -33
  551. package/OpenSpec-main/schemas/workspace-planning/templates/proposal.md +0 -28
  552. package/OpenSpec-main/schemas/workspace-planning/templates/spec.md +0 -9
  553. package/OpenSpec-main/schemas/workspace-planning/templates/tasks.md +0 -15
  554. package/OpenSpec-main/scripts/README.md +0 -37
  555. package/OpenSpec-main/scripts/pack-version-check.mjs +0 -111
  556. package/OpenSpec-main/scripts/postinstall.js +0 -83
  557. package/OpenSpec-main/scripts/test-postinstall.sh +0 -57
  558. package/OpenSpec-main/scripts/update-flake.sh +0 -128
  559. package/OpenSpec-main/test/cli-e2e/basic.test.ts +0 -205
  560. package/OpenSpec-main/test/commands/artifact-workflow.test.ts +0 -1063
  561. package/OpenSpec-main/test/commands/change-initiative-link.test.ts +0 -532
  562. package/OpenSpec-main/test/commands/change.interactive-show.test.ts +0 -45
  563. package/OpenSpec-main/test/commands/change.interactive-validate.test.ts +0 -48
  564. package/OpenSpec-main/test/commands/completion.test.ts +0 -278
  565. package/OpenSpec-main/test/commands/config-profile.test.ts +0 -532
  566. package/OpenSpec-main/test/commands/config.test.ts +0 -285
  567. package/OpenSpec-main/test/commands/context-store.test.ts +0 -692
  568. package/OpenSpec-main/test/commands/feedback.test.ts +0 -429
  569. package/OpenSpec-main/test/commands/initiative.test.ts +0 -907
  570. package/OpenSpec-main/test/commands/schema.test.ts +0 -467
  571. package/OpenSpec-main/test/commands/show.test.ts +0 -123
  572. package/OpenSpec-main/test/commands/spec.interactive-show.test.ts +0 -44
  573. package/OpenSpec-main/test/commands/spec.interactive-validate.test.ts +0 -44
  574. package/OpenSpec-main/test/commands/spec.test.ts +0 -324
  575. package/OpenSpec-main/test/commands/validate.enriched-output.test.ts +0 -49
  576. package/OpenSpec-main/test/commands/validate.test.ts +0 -147
  577. package/OpenSpec-main/test/commands/workspace-initiative-open.test.ts +0 -638
  578. package/OpenSpec-main/test/commands/workspace-open.test.ts +0 -123
  579. package/OpenSpec-main/test/commands/workspace.interactive.test.ts +0 -696
  580. package/OpenSpec-main/test/commands/workspace.test.ts +0 -1812
  581. package/OpenSpec-main/test/core/archive.test.ts +0 -869
  582. package/OpenSpec-main/test/core/artifact-graph/graph.test.ts +0 -268
  583. package/OpenSpec-main/test/core/artifact-graph/instruction-loader.test.ts +0 -609
  584. package/OpenSpec-main/test/core/artifact-graph/outputs.test.ts +0 -175
  585. package/OpenSpec-main/test/core/artifact-graph/resolver.test.ts +0 -651
  586. package/OpenSpec-main/test/core/artifact-graph/schema.test.ts +0 -207
  587. package/OpenSpec-main/test/core/artifact-graph/state.test.ts +0 -174
  588. package/OpenSpec-main/test/core/artifact-graph/workflow.integration.test.ts +0 -182
  589. package/OpenSpec-main/test/core/available-tools.test.ts +0 -167
  590. package/OpenSpec-main/test/core/collections/initiatives/operations.test.ts +0 -342
  591. package/OpenSpec-main/test/core/collections/initiatives/resolution.test.ts +0 -21
  592. package/OpenSpec-main/test/core/collections/initiatives/schema.test.ts +0 -201
  593. package/OpenSpec-main/test/core/collections/initiatives/templates.test.ts +0 -74
  594. package/OpenSpec-main/test/core/collections/runtime.test.ts +0 -214
  595. package/OpenSpec-main/test/core/command-generation/adapters.test.ts +0 -710
  596. package/OpenSpec-main/test/core/command-generation/generator.test.ts +0 -110
  597. package/OpenSpec-main/test/core/command-generation/registry.test.ts +0 -108
  598. package/OpenSpec-main/test/core/command-generation/types.test.ts +0 -79
  599. package/OpenSpec-main/test/core/commands/change-command.list.test.ts +0 -76
  600. package/OpenSpec-main/test/core/commands/change-command.show-validate.test.ts +0 -111
  601. package/OpenSpec-main/test/core/completions/command-registry.test.ts +0 -201
  602. package/OpenSpec-main/test/core/completions/completion-provider.test.ts +0 -288
  603. package/OpenSpec-main/test/core/completions/generators/bash-generator.test.ts +0 -586
  604. package/OpenSpec-main/test/core/completions/generators/fish-generator.test.ts +0 -549
  605. package/OpenSpec-main/test/core/completions/generators/powershell-generator.test.ts +0 -621
  606. package/OpenSpec-main/test/core/completions/generators/zsh-generator.test.ts +0 -425
  607. package/OpenSpec-main/test/core/completions/installers/bash-installer.test.ts +0 -484
  608. package/OpenSpec-main/test/core/completions/installers/fish-installer.test.ts +0 -321
  609. package/OpenSpec-main/test/core/completions/installers/powershell-installer.test.ts +0 -824
  610. package/OpenSpec-main/test/core/completions/installers/zsh-installer.test.ts +0 -750
  611. package/OpenSpec-main/test/core/config-schema.test.ts +0 -340
  612. package/OpenSpec-main/test/core/context-store/foundation.test.ts +0 -364
  613. package/OpenSpec-main/test/core/context-store/registry.test.ts +0 -599
  614. package/OpenSpec-main/test/core/converters/json-converter.test.ts +0 -184
  615. package/OpenSpec-main/test/core/global-config.test.ts +0 -371
  616. package/OpenSpec-main/test/core/init.test.ts +0 -786
  617. package/OpenSpec-main/test/core/legacy-cleanup.test.ts +0 -1162
  618. package/OpenSpec-main/test/core/list.test.ts +0 -165
  619. package/OpenSpec-main/test/core/migration.test.ts +0 -150
  620. package/OpenSpec-main/test/core/parsers/change-parser.test.ts +0 -52
  621. package/OpenSpec-main/test/core/parsers/markdown-parser.test.ts +0 -355
  622. package/OpenSpec-main/test/core/parsers/requirement-blocks.test.ts +0 -46
  623. package/OpenSpec-main/test/core/planning-home.test.ts +0 -120
  624. package/OpenSpec-main/test/core/profile-sync-drift.test.ts +0 -92
  625. package/OpenSpec-main/test/core/profiles.test.ts +0 -63
  626. package/OpenSpec-main/test/core/project-config.test.ts +0 -610
  627. package/OpenSpec-main/test/core/shared/skill-generation.test.ts +0 -301
  628. package/OpenSpec-main/test/core/shared/tool-detection.test.ts +0 -333
  629. package/OpenSpec-main/test/core/templates/skill-templates-parity.test.ts +0 -172
  630. package/OpenSpec-main/test/core/update.test.ts +0 -1810
  631. package/OpenSpec-main/test/core/validation.enriched-messages.test.ts +0 -74
  632. package/OpenSpec-main/test/core/validation.test.ts +0 -680
  633. package/OpenSpec-main/test/core/view.test.ts +0 -129
  634. package/OpenSpec-main/test/core/workspace/foundation.test.ts +0 -694
  635. package/OpenSpec-main/test/core/workspace/legacy-state.test.ts +0 -221
  636. package/OpenSpec-main/test/core/workspace/skills.test.ts +0 -69
  637. package/OpenSpec-main/test/fixtures/tmp-init/openspec/changes/c1/proposal.md +0 -7
  638. package/OpenSpec-main/test/fixtures/tmp-init/openspec/changes/c1/specs/alpha/spec.md +0 -8
  639. package/OpenSpec-main/test/fixtures/tmp-init/openspec/specs/alpha/spec.md +0 -12
  640. package/OpenSpec-main/test/helpers/path-env.ts +0 -26
  641. package/OpenSpec-main/test/helpers/run-cli.ts +0 -150
  642. package/OpenSpec-main/test/prompts/searchable-multi-select.test.ts +0 -220
  643. package/OpenSpec-main/test/specs/source-specs-normalization.test.ts +0 -63
  644. package/OpenSpec-main/test/telemetry/config.test.ts +0 -298
  645. package/OpenSpec-main/test/telemetry/index.test.ts +0 -219
  646. package/OpenSpec-main/test/utils/change-metadata.test.ts +0 -368
  647. package/OpenSpec-main/test/utils/change-utils.test.ts +0 -201
  648. package/OpenSpec-main/test/utils/command-references.test.ts +0 -83
  649. package/OpenSpec-main/test/utils/file-system.test.ts +0 -322
  650. package/OpenSpec-main/test/utils/interactive.test.ts +0 -125
  651. package/OpenSpec-main/test/utils/marker-updates.test.ts +0 -448
  652. package/OpenSpec-main/test/utils/shell-detection.test.ts +0 -185
  653. package/OpenSpec-main/vitest.config.ts +0 -47
  654. package/OpenSpec-main/vitest.setup.ts +0 -15
  655. package/Scanner CLI Inteligente para Projetos.md +0 -433
@@ -1,1810 +0,0 @@
1
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
- import { UpdateCommand, scanInstalledWorkflows } from '../../src/core/update.js';
3
- import { InitCommand } from '../../src/core/init.js';
4
- import { FileSystemUtils } from '../../src/utils/file-system.js';
5
- import { OPENSPEC_MARKERS } from '../../src/core/config.js';
6
- import type { GlobalConfig } from '../../src/core/global-config.js';
7
- import path from 'path';
8
- import fs from 'fs/promises';
9
- import os from 'os';
10
- import { randomUUID } from 'crypto';
11
-
12
- // Shared mutable mock config state
13
- const mockState = {
14
- config: {
15
- featureFlags: {},
16
- profile: 'core' as const,
17
- delivery: 'both' as const,
18
- } as GlobalConfig,
19
- };
20
-
21
- // Mock global config module to isolate tests from the machine's actual config
22
- vi.mock('../../src/core/global-config.js', async (importOriginal) => {
23
- const actual = await importOriginal<typeof import('../../src/core/global-config.js')>();
24
-
25
- return {
26
- ...actual,
27
- getGlobalConfig: () => ({ ...mockState.config }),
28
- saveGlobalConfig: vi.fn(),
29
- };
30
- });
31
-
32
- // Helper to set mock config for tests
33
- function setMockConfig(config: GlobalConfig) {
34
- mockState.config = config;
35
- }
36
-
37
- function resetMockConfig() {
38
- mockState.config = { featureFlags: {}, profile: 'core', delivery: 'both' };
39
- }
40
-
41
- describe('UpdateCommand', () => {
42
- let testDir: string;
43
- let updateCommand: UpdateCommand;
44
-
45
- beforeEach(async () => {
46
- // Create a temporary test directory
47
- testDir = path.join(os.tmpdir(), `openspec-test-${randomUUID()}`);
48
- await fs.mkdir(testDir, { recursive: true });
49
-
50
- // Create openspec directory
51
- const openspecDir = path.join(testDir, 'openspec');
52
- await fs.mkdir(openspecDir, { recursive: true });
53
-
54
- updateCommand = new UpdateCommand();
55
-
56
- // Reset mock config to defaults
57
- resetMockConfig();
58
-
59
- // Clear all mocks before each test
60
- vi.restoreAllMocks();
61
- });
62
-
63
- afterEach(async () => {
64
- // Restore all mocks after each test
65
- vi.restoreAllMocks();
66
-
67
- // Clean up test directory
68
- await fs.rm(testDir, { recursive: true, force: true });
69
- });
70
-
71
- describe('basic validation', () => {
72
- it('should throw error if openspec directory does not exist', async () => {
73
- // Remove openspec directory
74
- await fs.rm(path.join(testDir, 'openspec'), {
75
- recursive: true,
76
- force: true,
77
- });
78
-
79
- await expect(updateCommand.execute(testDir)).rejects.toThrow(
80
- "No OpenSpec directory found. Run 'openspec init' first."
81
- );
82
- });
83
-
84
- it('should report no configured tools when none exist', async () => {
85
- const consoleSpy = vi.spyOn(console, 'log');
86
-
87
- await updateCommand.execute(testDir);
88
-
89
- expect(consoleSpy).toHaveBeenCalledWith(
90
- expect.stringContaining('No configured tools found')
91
- );
92
-
93
- consoleSpy.mockRestore();
94
- });
95
- });
96
-
97
- describe('skill updates', () => {
98
- it('should update skill files for configured Claude tool', async () => {
99
- // Set up a configured Claude tool by creating skill directories
100
- const skillsDir = path.join(testDir, '.claude', 'skills');
101
- const exploreSkillDir = path.join(skillsDir, 'openspec-explore');
102
- await fs.mkdir(exploreSkillDir, { recursive: true });
103
-
104
- // Create an existing skill file
105
- const oldSkillContent = `---
106
- name: openspec-explore (old)
107
- description: Old description
108
- license: MIT
109
- compatibility: Requires openspec CLI.
110
- metadata:
111
- author: openspec
112
- version: "0.9"
113
- ---
114
-
115
- Old instructions content
116
- `;
117
- await fs.writeFile(
118
- path.join(exploreSkillDir, 'SKILL.md'),
119
- oldSkillContent
120
- );
121
-
122
- const consoleSpy = vi.spyOn(console, 'log');
123
-
124
- await updateCommand.execute(testDir);
125
-
126
- // Check skill file was updated
127
- const updatedSkill = await fs.readFile(
128
- path.join(exploreSkillDir, 'SKILL.md'),
129
- 'utf-8'
130
- );
131
- expect(updatedSkill).toContain('name: openspec-explore');
132
- expect(updatedSkill).not.toContain('Old instructions content');
133
- expect(updatedSkill).toContain('license: MIT');
134
-
135
- // Check console output
136
- expect(consoleSpy).toHaveBeenCalledWith(
137
- expect.stringContaining('Updating 1 tool(s): claude')
138
- );
139
-
140
- consoleSpy.mockRestore();
141
- });
142
-
143
- it('should update core profile skill files when tool is configured', async () => {
144
- // Set up a configured tool with one skill directory
145
- const skillsDir = path.join(testDir, '.claude', 'skills');
146
-
147
- // Create at least one skill to mark tool as configured
148
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
149
- recursive: true,
150
- });
151
- await fs.writeFile(
152
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
153
- 'old content'
154
- );
155
-
156
- await updateCommand.execute(testDir);
157
-
158
- // Verify core profile skill files were created/updated (propose, explore, apply, sync, archive)
159
- const coreSkillNames = [
160
- 'openspec-explore',
161
- 'openspec-apply-change',
162
- 'openspec-sync-specs',
163
- 'openspec-archive-change',
164
- 'openspec-propose',
165
- ];
166
-
167
- for (const skillName of coreSkillNames) {
168
- const skillFile = path.join(skillsDir, skillName, 'SKILL.md');
169
- const exists = await FileSystemUtils.fileExists(skillFile);
170
- expect(exists).toBe(true);
171
-
172
- const content = await fs.readFile(skillFile, 'utf-8');
173
- expect(content).toContain('---');
174
- expect(content).toContain('name:');
175
- expect(content).toContain('description:');
176
- }
177
-
178
- // Verify non-core skills are NOT created
179
- const nonCoreSkillNames = [
180
- 'openspec-new-change',
181
- 'openspec-continue-change',
182
- 'openspec-ff-change',
183
- 'openspec-bulk-archive-change',
184
- 'openspec-verify-change',
185
- ];
186
-
187
- for (const skillName of nonCoreSkillNames) {
188
- const skillFile = path.join(skillsDir, skillName, 'SKILL.md');
189
- const exists = await FileSystemUtils.fileExists(skillFile);
190
- expect(exists).toBe(false);
191
- }
192
- });
193
- });
194
-
195
- describe('command updates', () => {
196
- it('should update opsx commands for configured Claude tool', async () => {
197
- // Set up a configured Claude tool
198
- const skillsDir = path.join(testDir, '.claude', 'skills');
199
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
200
- recursive: true,
201
- });
202
- await fs.writeFile(
203
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
204
- 'old content'
205
- );
206
-
207
- await updateCommand.execute(testDir);
208
-
209
- // Check opsx command files were created
210
- const commandsDir = path.join(testDir, '.claude', 'commands', 'opsx');
211
- const exploreCmd = path.join(commandsDir, 'explore.md');
212
- const exists = await FileSystemUtils.fileExists(exploreCmd);
213
- expect(exists).toBe(true);
214
-
215
- const content = await fs.readFile(exploreCmd, 'utf-8');
216
- expect(content).toContain('---');
217
- expect(content).toContain('name:');
218
- expect(content).toContain('description:');
219
- expect(content).toContain('category:');
220
- expect(content).toContain('tags:');
221
- });
222
-
223
- it('should update core profile opsx commands when tool is configured', async () => {
224
- // Set up a configured tool
225
- const skillsDir = path.join(testDir, '.claude', 'skills');
226
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
227
- recursive: true,
228
- });
229
- await fs.writeFile(
230
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
231
- 'old content'
232
- );
233
-
234
- await updateCommand.execute(testDir);
235
-
236
- // Verify core profile commands were created (propose, explore, apply, sync, archive)
237
- const coreCommandIds = ['explore', 'apply', 'sync', 'archive', 'propose'];
238
- const commandsDir = path.join(testDir, '.claude', 'commands', 'opsx');
239
- for (const cmdId of coreCommandIds) {
240
- const cmdFile = path.join(commandsDir, `${cmdId}.md`);
241
- const exists = await FileSystemUtils.fileExists(cmdFile);
242
- expect(exists).toBe(true);
243
- }
244
-
245
- // Verify non-core commands are NOT created
246
- const nonCoreCommandIds = ['new', 'continue', 'ff', 'bulk-archive', 'verify'];
247
- for (const cmdId of nonCoreCommandIds) {
248
- const cmdFile = path.join(commandsDir, `${cmdId}.md`);
249
- const exists = await FileSystemUtils.fileExists(cmdFile);
250
- expect(exists).toBe(false);
251
- }
252
- });
253
-
254
- });
255
-
256
- describe('multi-tool support', () => {
257
- it('should update multiple configured tools', async () => {
258
- // Set up Claude
259
- const claudeSkillsDir = path.join(testDir, '.claude', 'skills');
260
- await fs.mkdir(path.join(claudeSkillsDir, 'openspec-explore'), {
261
- recursive: true,
262
- });
263
- await fs.writeFile(
264
- path.join(claudeSkillsDir, 'openspec-explore', 'SKILL.md'),
265
- 'old'
266
- );
267
-
268
- // Set up Cursor
269
- const cursorSkillsDir = path.join(testDir, '.cursor', 'skills');
270
- await fs.mkdir(path.join(cursorSkillsDir, 'openspec-explore'), {
271
- recursive: true,
272
- });
273
- await fs.writeFile(
274
- path.join(cursorSkillsDir, 'openspec-explore', 'SKILL.md'),
275
- 'old'
276
- );
277
-
278
- const consoleSpy = vi.spyOn(console, 'log');
279
-
280
- await updateCommand.execute(testDir);
281
-
282
- // Both tools should be updated
283
- expect(consoleSpy).toHaveBeenCalledWith(
284
- expect.stringContaining('Updating 2 tool(s)')
285
- );
286
-
287
- // Verify Claude skills updated
288
- const claudeSkill = await fs.readFile(
289
- path.join(claudeSkillsDir, 'openspec-explore', 'SKILL.md'),
290
- 'utf-8'
291
- );
292
- expect(claudeSkill).toContain('name: openspec-explore');
293
-
294
- // Verify Cursor skills updated
295
- const cursorSkill = await fs.readFile(
296
- path.join(cursorSkillsDir, 'openspec-explore', 'SKILL.md'),
297
- 'utf-8'
298
- );
299
- expect(cursorSkill).toContain('name: openspec-explore');
300
-
301
- consoleSpy.mockRestore();
302
- });
303
-
304
- it('should update Qwen tool with correct command format', async () => {
305
- // Set up Qwen
306
- const qwenSkillsDir = path.join(testDir, '.qwen', 'skills');
307
- await fs.mkdir(path.join(qwenSkillsDir, 'openspec-explore'), {
308
- recursive: true,
309
- });
310
- await fs.writeFile(
311
- path.join(qwenSkillsDir, 'openspec-explore', 'SKILL.md'),
312
- 'old'
313
- );
314
-
315
- await updateCommand.execute(testDir);
316
-
317
- // Check Qwen command format (TOML) - Qwen uses flat path structure: opsx-<id>.toml
318
- const qwenCmd = path.join(
319
- testDir,
320
- '.qwen',
321
- 'commands',
322
- 'opsx-explore.toml'
323
- );
324
- const exists = await FileSystemUtils.fileExists(qwenCmd);
325
- expect(exists).toBe(true);
326
-
327
- const content = await fs.readFile(qwenCmd, 'utf-8');
328
- expect(content).toContain('description =');
329
- expect(content).toContain('prompt =');
330
- });
331
-
332
- it('should update Windsurf tool with correct command format', async () => {
333
- // Set up Windsurf
334
- const windsurfSkillsDir = path.join(testDir, '.windsurf', 'skills');
335
- await fs.mkdir(path.join(windsurfSkillsDir, 'openspec-explore'), {
336
- recursive: true,
337
- });
338
- await fs.writeFile(
339
- path.join(windsurfSkillsDir, 'openspec-explore', 'SKILL.md'),
340
- 'old'
341
- );
342
-
343
- await updateCommand.execute(testDir);
344
-
345
- // Check Windsurf command format
346
- const windsurfCmd = path.join(
347
- testDir,
348
- '.windsurf',
349
- 'workflows',
350
- 'opsx-explore.md'
351
- );
352
- const exists = await FileSystemUtils.fileExists(windsurfCmd);
353
- expect(exists).toBe(true);
354
-
355
- const content = await fs.readFile(windsurfCmd, 'utf-8');
356
- expect(content).toContain('---');
357
- expect(content).toContain('name:');
358
- });
359
- });
360
-
361
- describe('error handling', () => {
362
- it('should handle tool update failures gracefully', async () => {
363
- // Set up a configured tool
364
- const skillsDir = path.join(testDir, '.claude', 'skills');
365
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
366
- recursive: true,
367
- });
368
- await fs.writeFile(
369
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
370
- 'old'
371
- );
372
-
373
- // Mock writeFile to fail for skills
374
- const originalWriteFile = FileSystemUtils.writeFile.bind(FileSystemUtils);
375
- const writeSpy = vi
376
- .spyOn(FileSystemUtils, 'writeFile')
377
- .mockImplementation(async (filePath, content) => {
378
- if (filePath.includes('SKILL.md')) {
379
- throw new Error('EACCES: permission denied');
380
- }
381
- return originalWriteFile(filePath, content);
382
- });
383
-
384
- const consoleSpy = vi.spyOn(console, 'log');
385
-
386
- // Should not throw
387
- await updateCommand.execute(testDir);
388
-
389
- // Should report failure
390
- expect(consoleSpy).toHaveBeenCalledWith(
391
- expect.stringContaining('Failed')
392
- );
393
-
394
- writeSpy.mockRestore();
395
- consoleSpy.mockRestore();
396
- });
397
-
398
- it('should continue updating other tools when one fails', async () => {
399
- // Set up Claude and Cursor
400
- const claudeSkillsDir = path.join(testDir, '.claude', 'skills');
401
- await fs.mkdir(path.join(claudeSkillsDir, 'openspec-explore'), {
402
- recursive: true,
403
- });
404
- await fs.writeFile(
405
- path.join(claudeSkillsDir, 'openspec-explore', 'SKILL.md'),
406
- 'old'
407
- );
408
-
409
- const cursorSkillsDir = path.join(testDir, '.cursor', 'skills');
410
- await fs.mkdir(path.join(cursorSkillsDir, 'openspec-explore'), {
411
- recursive: true,
412
- });
413
- await fs.writeFile(
414
- path.join(cursorSkillsDir, 'openspec-explore', 'SKILL.md'),
415
- 'old'
416
- );
417
-
418
- // Mock writeFile to fail only for Claude
419
- const originalWriteFile = FileSystemUtils.writeFile.bind(FileSystemUtils);
420
- const writeSpy = vi
421
- .spyOn(FileSystemUtils, 'writeFile')
422
- .mockImplementation(async (filePath, content) => {
423
- if (filePath.includes('.claude') && filePath.includes('SKILL.md')) {
424
- throw new Error('EACCES: permission denied');
425
- }
426
- return originalWriteFile(filePath, content);
427
- });
428
-
429
- const consoleSpy = vi.spyOn(console, 'log');
430
-
431
- await updateCommand.execute(testDir);
432
-
433
- // Cursor should still be updated - check the actual format from ora spinner
434
- expect(consoleSpy).toHaveBeenCalledWith(
435
- expect.stringContaining('Updated: Cursor')
436
- );
437
-
438
- // Claude should be reported as failed
439
- expect(consoleSpy).toHaveBeenCalledWith(
440
- expect.stringContaining('Failed')
441
- );
442
-
443
- writeSpy.mockRestore();
444
- consoleSpy.mockRestore();
445
- });
446
- });
447
-
448
- describe('tool detection', () => {
449
- it('should detect tool as configured only when skill file exists', async () => {
450
- // Create skills directory but no skill files
451
- const skillsDir = path.join(testDir, '.claude', 'skills');
452
- await fs.mkdir(skillsDir, { recursive: true });
453
-
454
- const consoleSpy = vi.spyOn(console, 'log');
455
-
456
- await updateCommand.execute(testDir);
457
-
458
- // Should report no configured tools
459
- expect(consoleSpy).toHaveBeenCalledWith(
460
- expect.stringContaining('No configured tools found')
461
- );
462
-
463
- consoleSpy.mockRestore();
464
- });
465
-
466
- it('should detect tool when any single skill exists', async () => {
467
- // Create only one skill file
468
- const skillDir = path.join(
469
- testDir,
470
- '.claude',
471
- 'skills',
472
- 'openspec-archive-change'
473
- );
474
- await fs.mkdir(skillDir, { recursive: true });
475
- await fs.writeFile(path.join(skillDir, 'SKILL.md'), 'old');
476
-
477
- const consoleSpy = vi.spyOn(console, 'log');
478
-
479
- await updateCommand.execute(testDir);
480
-
481
- // Should detect and update Claude
482
- expect(consoleSpy).toHaveBeenCalledWith(
483
- expect.stringContaining('Updating 1 tool(s): claude')
484
- );
485
-
486
- consoleSpy.mockRestore();
487
- });
488
- });
489
-
490
- describe('skill content validation', () => {
491
- it('should generate valid YAML frontmatter in skill files', async () => {
492
- // Set up a configured tool
493
- const skillsDir = path.join(testDir, '.claude', 'skills');
494
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
495
- recursive: true,
496
- });
497
- await fs.writeFile(
498
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
499
- 'old'
500
- );
501
-
502
- await updateCommand.execute(testDir);
503
-
504
- const skillContent = await fs.readFile(
505
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
506
- 'utf-8'
507
- );
508
-
509
- // Validate frontmatter structure
510
- expect(skillContent).toMatch(/^---\n/);
511
- expect(skillContent).toContain('name:');
512
- expect(skillContent).toContain('description:');
513
- expect(skillContent).toContain('license:');
514
- expect(skillContent).toContain('compatibility:');
515
- expect(skillContent).toContain('metadata:');
516
- expect(skillContent).toContain('author:');
517
- expect(skillContent).toContain('version:');
518
- expect(skillContent).toMatch(/---\n\n/);
519
- });
520
-
521
- it('should include proper instructions in skill files', async () => {
522
- // Set up a configured tool with apply-change skill (which is in core profile)
523
- const skillsDir = path.join(testDir, '.claude', 'skills');
524
- await fs.mkdir(path.join(skillsDir, 'openspec-apply-change'), {
525
- recursive: true,
526
- });
527
- await fs.writeFile(
528
- path.join(skillsDir, 'openspec-apply-change', 'SKILL.md'),
529
- 'old'
530
- );
531
-
532
- await updateCommand.execute(testDir);
533
-
534
- const skillContent = await fs.readFile(
535
- path.join(skillsDir, 'openspec-apply-change', 'SKILL.md'),
536
- 'utf-8'
537
- );
538
-
539
- // Apply skill should contain implementation instructions
540
- expect(skillContent.toLowerCase()).toContain('task');
541
- });
542
- });
543
-
544
- describe('success output', () => {
545
- it('should display success message with tool name', async () => {
546
- // Set up a configured tool
547
- const skillsDir = path.join(testDir, '.claude', 'skills');
548
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
549
- recursive: true,
550
- });
551
- await fs.writeFile(
552
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
553
- 'old'
554
- );
555
-
556
- const consoleSpy = vi.spyOn(console, 'log');
557
-
558
- await updateCommand.execute(testDir);
559
-
560
- // The success output uses "✓ Updated: <name>"
561
- expect(consoleSpy).toHaveBeenCalledWith(
562
- expect.stringContaining('Updated: Claude Code')
563
- );
564
-
565
- consoleSpy.mockRestore();
566
- });
567
-
568
- it('should suggest IDE restart after update', async () => {
569
- // Set up a configured tool
570
- const skillsDir = path.join(testDir, '.claude', 'skills');
571
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
572
- recursive: true,
573
- });
574
- await fs.writeFile(
575
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
576
- 'old'
577
- );
578
-
579
- const consoleSpy = vi.spyOn(console, 'log');
580
-
581
- await updateCommand.execute(testDir);
582
-
583
- expect(consoleSpy).toHaveBeenCalledWith(
584
- expect.stringContaining('Restart your IDE')
585
- );
586
-
587
- consoleSpy.mockRestore();
588
- });
589
- });
590
-
591
- describe('smart update detection', () => {
592
- it('should show "up to date" message when skills have current version', async () => {
593
- // Initialize full core profile output so there is no profile/delivery drift.
594
- const initCommand = new InitCommand({ tools: 'claude', force: true });
595
- await initCommand.execute(testDir);
596
-
597
- const consoleSpy = vi.spyOn(console, 'log');
598
-
599
- await updateCommand.execute(testDir);
600
-
601
- expect(consoleSpy).toHaveBeenCalledWith(
602
- expect.stringContaining('up to date')
603
- );
604
- expect(consoleSpy).toHaveBeenCalledWith(
605
- expect.stringContaining('--force')
606
- );
607
-
608
- consoleSpy.mockRestore();
609
- });
610
-
611
- it('should detect update needed when generatedBy is missing', async () => {
612
- // Set up a configured tool without generatedBy
613
- const skillsDir = path.join(testDir, '.claude', 'skills');
614
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
615
- recursive: true,
616
- });
617
- await fs.writeFile(
618
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
619
- `---
620
- name: openspec-explore
621
- metadata:
622
- author: openspec
623
- version: "1.0"
624
- ---
625
-
626
- Legacy content without generatedBy
627
- `
628
- );
629
-
630
- const consoleSpy = vi.spyOn(console, 'log');
631
-
632
- await updateCommand.execute(testDir);
633
-
634
- // Should show "unknown → version" in the update message
635
- expect(consoleSpy).toHaveBeenCalledWith(
636
- expect.stringContaining('unknown')
637
- );
638
-
639
- consoleSpy.mockRestore();
640
- });
641
-
642
- it('should detect update needed when version differs', async () => {
643
- // Set up a configured tool with old version
644
- const skillsDir = path.join(testDir, '.claude', 'skills');
645
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
646
- recursive: true,
647
- });
648
- await fs.writeFile(
649
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
650
- `---
651
- name: openspec-explore
652
- metadata:
653
- generatedBy: "0.1.0"
654
- ---
655
-
656
- Old version content
657
- `
658
- );
659
-
660
- const consoleSpy = vi.spyOn(console, 'log');
661
-
662
- await updateCommand.execute(testDir);
663
-
664
- // Should show version transition
665
- expect(consoleSpy).toHaveBeenCalledWith(
666
- expect.stringContaining('0.1.0')
667
- );
668
-
669
- consoleSpy.mockRestore();
670
- });
671
-
672
- it('should embed generatedBy in updated skill files', async () => {
673
- // Set up a configured tool without generatedBy
674
- const skillsDir = path.join(testDir, '.claude', 'skills');
675
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
676
- recursive: true,
677
- });
678
- await fs.writeFile(
679
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
680
- 'old content without version'
681
- );
682
-
683
- await updateCommand.execute(testDir);
684
-
685
- const updatedContent = await fs.readFile(
686
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
687
- 'utf-8'
688
- );
689
-
690
- // Should contain generatedBy field
691
- expect(updatedContent).toMatch(/generatedBy:\s*["']\d+\.\d+\.\d+["']/);
692
- });
693
- });
694
-
695
- describe('--force flag', () => {
696
- it('should update when force is true even if up to date', async () => {
697
- // Set up a configured tool with current version
698
- const skillsDir = path.join(testDir, '.claude', 'skills');
699
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
700
- recursive: true,
701
- });
702
-
703
- const { version } = await import('../../package.json');
704
- await fs.writeFile(
705
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
706
- `---
707
- metadata:
708
- generatedBy: "${version}"
709
- ---
710
- Content
711
- `
712
- );
713
-
714
- const consoleSpy = vi.spyOn(console, 'log');
715
-
716
- // Create update command with force option
717
- const forceUpdateCommand = new UpdateCommand({ force: true });
718
- await forceUpdateCommand.execute(testDir);
719
-
720
- // Should show "Force updating" message
721
- expect(consoleSpy).toHaveBeenCalledWith(
722
- expect.stringContaining('Force updating')
723
- );
724
-
725
- // Should show updated message
726
- expect(consoleSpy).toHaveBeenCalledWith(
727
- expect.stringContaining('Updated: Claude Code')
728
- );
729
-
730
- consoleSpy.mockRestore();
731
- });
732
-
733
- it('should not show --force hint when force is used', async () => {
734
- // Set up a configured tool
735
- const skillsDir = path.join(testDir, '.claude', 'skills');
736
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
737
- recursive: true,
738
- });
739
- await fs.writeFile(
740
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
741
- 'old content'
742
- );
743
-
744
- const consoleSpy = vi.spyOn(console, 'log');
745
-
746
- const forceUpdateCommand = new UpdateCommand({ force: true });
747
- await forceUpdateCommand.execute(testDir);
748
-
749
- // Get all console.log calls as strings
750
- const allCalls = consoleSpy.mock.calls.map(call =>
751
- call.map(arg => String(arg)).join(' ')
752
- );
753
-
754
- // Should not show "Use --force" since force was used
755
- const hasForceHint = allCalls.some(call => call.includes('Use --force'));
756
- expect(hasForceHint).toBe(false);
757
-
758
- consoleSpy.mockRestore();
759
- });
760
-
761
- it('should update all tools when force is used with mixed versions', async () => {
762
- // Set up Claude with current version
763
- const { version } = await import('../../package.json');
764
- const claudeSkillDir = path.join(testDir, '.claude', 'skills', 'openspec-explore');
765
- await fs.mkdir(claudeSkillDir, { recursive: true });
766
- await fs.writeFile(
767
- path.join(claudeSkillDir, 'SKILL.md'),
768
- `---
769
- metadata:
770
- generatedBy: "${version}"
771
- ---
772
- `
773
- );
774
-
775
- // Set up Cursor with old version
776
- const cursorSkillDir = path.join(testDir, '.cursor', 'skills', 'openspec-explore');
777
- await fs.mkdir(cursorSkillDir, { recursive: true });
778
- await fs.writeFile(
779
- path.join(cursorSkillDir, 'SKILL.md'),
780
- `---
781
- metadata:
782
- generatedBy: "0.1.0"
783
- ---
784
- `
785
- );
786
-
787
- const consoleSpy = vi.spyOn(console, 'log');
788
-
789
- const forceUpdateCommand = new UpdateCommand({ force: true });
790
- await forceUpdateCommand.execute(testDir);
791
-
792
- // Should show both tools being force updated
793
- expect(consoleSpy).toHaveBeenCalledWith(
794
- expect.stringContaining('Force updating 2 tool(s)')
795
- );
796
-
797
- consoleSpy.mockRestore();
798
- });
799
- });
800
-
801
- describe('version tracking', () => {
802
- it('should show version in success message', async () => {
803
- // Set up a configured tool
804
- const skillsDir = path.join(testDir, '.claude', 'skills');
805
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
806
- recursive: true,
807
- });
808
- await fs.writeFile(
809
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
810
- 'old'
811
- );
812
-
813
- const consoleSpy = vi.spyOn(console, 'log');
814
-
815
- await updateCommand.execute(testDir);
816
-
817
- // Should show version in success message
818
- const { version } = await import('../../package.json');
819
- expect(consoleSpy).toHaveBeenCalledWith(
820
- expect.stringContaining(`(v${version})`)
821
- );
822
-
823
- consoleSpy.mockRestore();
824
- });
825
-
826
- it('should only update tools that need updating', async () => {
827
- // Initialize both tools so Cursor is fully synced with profile/delivery.
828
- const initCommand = new InitCommand({ tools: 'claude,cursor', force: true });
829
- await initCommand.execute(testDir);
830
-
831
- // Make Claude stale to force a version update.
832
- const claudeSkillFile = path.join(testDir, '.claude', 'skills', 'openspec-explore', 'SKILL.md');
833
- const claudeContent = await fs.readFile(claudeSkillFile, 'utf-8');
834
- await fs.writeFile(
835
- claudeSkillFile,
836
- claudeContent.replace(/generatedBy:\s*["'][^"']+["']/, 'generatedBy: "0.1.0"')
837
- );
838
-
839
- const consoleSpy = vi.spyOn(console, 'log');
840
-
841
- await updateCommand.execute(testDir);
842
-
843
- // Should show only Claude being updated
844
- expect(consoleSpy).toHaveBeenCalledWith(
845
- expect.stringContaining('Updating 1 tool(s)')
846
- );
847
-
848
- // Should mention Cursor is already up to date
849
- expect(consoleSpy).toHaveBeenCalledWith(
850
- expect.stringContaining('Already up to date: cursor')
851
- );
852
-
853
- consoleSpy.mockRestore();
854
- });
855
- });
856
-
857
- describe('legacy cleanup', () => {
858
- it('should detect and auto-cleanup legacy files with --force flag', async () => {
859
- // Set up a configured tool
860
- const skillsDir = path.join(testDir, '.claude', 'skills');
861
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
862
- recursive: true,
863
- });
864
- await fs.writeFile(
865
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
866
- 'old'
867
- );
868
-
869
- // Create legacy CLAUDE.md with OpenSpec markers
870
- const legacyContent = `${OPENSPEC_MARKERS.start}
871
- # OpenSpec Instructions
872
-
873
- These instructions are for AI assistants.
874
- ${OPENSPEC_MARKERS.end}
875
- `;
876
- await fs.writeFile(path.join(testDir, 'CLAUDE.md'), legacyContent);
877
-
878
- const consoleSpy = vi.spyOn(console, 'log');
879
-
880
- // Create update command with force option
881
- const forceUpdateCommand = new UpdateCommand({ force: true });
882
- await forceUpdateCommand.execute(testDir);
883
-
884
- // Should show v1 upgrade message
885
- expect(consoleSpy).toHaveBeenCalledWith(
886
- expect.stringContaining('Upgrading to the new OpenSpec')
887
- );
888
-
889
- // Should show marker removal message (config files are never deleted, only have markers removed)
890
- expect(consoleSpy).toHaveBeenCalledWith(
891
- expect.stringContaining('Removed OpenSpec markers from CLAUDE.md')
892
- );
893
-
894
- // Config file should still exist (never deleted)
895
- const legacyExists = await FileSystemUtils.fileExists(
896
- path.join(testDir, 'CLAUDE.md')
897
- );
898
- expect(legacyExists).toBe(true);
899
-
900
- // File should have markers removed
901
- const content = await fs.readFile(path.join(testDir, 'CLAUDE.md'), 'utf-8');
902
- expect(content).not.toContain(OPENSPEC_MARKERS.start);
903
- expect(content).not.toContain(OPENSPEC_MARKERS.end);
904
-
905
- consoleSpy.mockRestore();
906
- });
907
-
908
- it('should warn but continue with update when legacy files found in non-interactive mode', async () => {
909
- // Set up a configured tool
910
- const skillsDir = path.join(testDir, '.claude', 'skills');
911
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
912
- recursive: true,
913
- });
914
- await fs.writeFile(
915
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
916
- 'old'
917
- );
918
-
919
- // Create legacy CLAUDE.md with OpenSpec markers
920
- const legacyContent = `${OPENSPEC_MARKERS.start}
921
- # OpenSpec Instructions
922
- ${OPENSPEC_MARKERS.end}
923
- `;
924
- await fs.writeFile(path.join(testDir, 'CLAUDE.md'), legacyContent);
925
-
926
- const consoleSpy = vi.spyOn(console, 'log');
927
-
928
- // Run without --force in non-interactive mode (CI environment)
929
- await updateCommand.execute(testDir);
930
-
931
- // Should show v1 upgrade message
932
- expect(consoleSpy).toHaveBeenCalledWith(
933
- expect.stringContaining('Upgrading to the new OpenSpec')
934
- );
935
-
936
- // Should show warning about --force
937
- expect(consoleSpy).toHaveBeenCalledWith(
938
- expect.stringContaining('Run with --force to auto-cleanup')
939
- );
940
-
941
- // Should continue with update
942
- expect(consoleSpy).toHaveBeenCalledWith(
943
- expect.stringContaining('Updated: Claude Code')
944
- );
945
-
946
- // Legacy file should still exist (not cleaned up)
947
- const legacyExists = await FileSystemUtils.fileExists(
948
- path.join(testDir, 'CLAUDE.md')
949
- );
950
- expect(legacyExists).toBe(true);
951
-
952
- consoleSpy.mockRestore();
953
- });
954
-
955
- it('should cleanup legacy slash command directories with --force', async () => {
956
- // Set up a configured tool
957
- const skillsDir = path.join(testDir, '.claude', 'skills');
958
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
959
- recursive: true,
960
- });
961
- await fs.writeFile(
962
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
963
- 'old'
964
- );
965
-
966
- // Create legacy slash command directory
967
- const legacyCommandDir = path.join(testDir, '.claude', 'commands', 'openspec');
968
- await fs.mkdir(legacyCommandDir, { recursive: true });
969
- await fs.writeFile(
970
- path.join(legacyCommandDir, 'old-command.md'),
971
- 'old command'
972
- );
973
-
974
- const consoleSpy = vi.spyOn(console, 'log');
975
-
976
- // Create update command with force option
977
- const forceUpdateCommand = new UpdateCommand({ force: true });
978
- await forceUpdateCommand.execute(testDir);
979
-
980
- // Should show cleanup message for directory
981
- expect(consoleSpy).toHaveBeenCalledWith(
982
- expect.stringContaining('Removed .claude/commands/openspec/')
983
- );
984
-
985
- // Legacy directory should be deleted
986
- const legacyDirExists = await FileSystemUtils.directoryExists(legacyCommandDir);
987
- expect(legacyDirExists).toBe(false);
988
-
989
- consoleSpy.mockRestore();
990
- });
991
-
992
- it('should cleanup legacy openspec/AGENTS.md with --force', async () => {
993
- // Set up a configured tool
994
- const skillsDir = path.join(testDir, '.claude', 'skills');
995
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
996
- recursive: true,
997
- });
998
- await fs.writeFile(
999
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
1000
- 'old'
1001
- );
1002
-
1003
- // Create legacy openspec/AGENTS.md
1004
- await fs.writeFile(
1005
- path.join(testDir, 'openspec', 'AGENTS.md'),
1006
- '# Old AGENTS.md content'
1007
- );
1008
-
1009
- const consoleSpy = vi.spyOn(console, 'log');
1010
-
1011
- // Create update command with force option
1012
- const forceUpdateCommand = new UpdateCommand({ force: true });
1013
- await forceUpdateCommand.execute(testDir);
1014
-
1015
- // Should show cleanup message
1016
- expect(consoleSpy).toHaveBeenCalledWith(
1017
- expect.stringContaining('Removed openspec/AGENTS.md')
1018
- );
1019
-
1020
- // Legacy file should be deleted
1021
- const legacyExists = await FileSystemUtils.fileExists(
1022
- path.join(testDir, 'openspec', 'AGENTS.md')
1023
- );
1024
- expect(legacyExists).toBe(false);
1025
-
1026
- consoleSpy.mockRestore();
1027
- });
1028
-
1029
- it('should not show legacy cleanup messages when no legacy files exist', async () => {
1030
- // Set up a configured tool with no legacy files
1031
- const skillsDir = path.join(testDir, '.claude', 'skills');
1032
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
1033
- recursive: true,
1034
- });
1035
- await fs.writeFile(
1036
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
1037
- 'old'
1038
- );
1039
-
1040
- const consoleSpy = vi.spyOn(console, 'log');
1041
-
1042
- await updateCommand.execute(testDir);
1043
-
1044
- // Should not show v1 upgrade message (no legacy files)
1045
- const calls = consoleSpy.mock.calls.map(call =>
1046
- call.map(arg => String(arg)).join(' ')
1047
- );
1048
- const hasLegacyMessage = calls.some(call =>
1049
- call.includes('Upgrading to the new OpenSpec')
1050
- );
1051
- expect(hasLegacyMessage).toBe(false);
1052
-
1053
- consoleSpy.mockRestore();
1054
- });
1055
-
1056
- it('should remove OpenSpec marker block from mixed content files', async () => {
1057
- // Set up a configured tool
1058
- const skillsDir = path.join(testDir, '.claude', 'skills');
1059
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), {
1060
- recursive: true,
1061
- });
1062
- await fs.writeFile(
1063
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
1064
- 'old'
1065
- );
1066
-
1067
- // Create CLAUDE.md with mixed content (user content + OpenSpec markers)
1068
- const mixedContent = `# My Project
1069
-
1070
- Some user-defined instructions here.
1071
-
1072
- ${OPENSPEC_MARKERS.start}
1073
- # OpenSpec Instructions
1074
-
1075
- These instructions are for AI assistants.
1076
- ${OPENSPEC_MARKERS.end}
1077
-
1078
- More user content after markers.
1079
- `;
1080
- await fs.writeFile(path.join(testDir, 'CLAUDE.md'), mixedContent);
1081
-
1082
- const consoleSpy = vi.spyOn(console, 'log');
1083
-
1084
- // Create update command with force option
1085
- const forceUpdateCommand = new UpdateCommand({ force: true });
1086
- await forceUpdateCommand.execute(testDir);
1087
-
1088
- // Should show marker removal message
1089
- expect(consoleSpy).toHaveBeenCalledWith(
1090
- expect.stringContaining('Removed OpenSpec markers from CLAUDE.md')
1091
- );
1092
-
1093
- // File should still exist
1094
- const fileExists = await FileSystemUtils.fileExists(
1095
- path.join(testDir, 'CLAUDE.md')
1096
- );
1097
- expect(fileExists).toBe(true);
1098
-
1099
- // File should have markers removed but preserve user content
1100
- const updatedContent = await fs.readFile(
1101
- path.join(testDir, 'CLAUDE.md'),
1102
- 'utf-8'
1103
- );
1104
- expect(updatedContent).toContain('# My Project');
1105
- expect(updatedContent).toContain('Some user-defined instructions here');
1106
- expect(updatedContent).toContain('More user content after markers');
1107
- expect(updatedContent).not.toContain(OPENSPEC_MARKERS.start);
1108
- expect(updatedContent).not.toContain(OPENSPEC_MARKERS.end);
1109
-
1110
- consoleSpy.mockRestore();
1111
- });
1112
- });
1113
-
1114
- describe('legacy tool upgrade', () => {
1115
- it('should upgrade legacy tools to new skills with --force', async () => {
1116
- // Create legacy slash command directory (no skills exist yet)
1117
- const legacyCommandDir = path.join(testDir, '.claude', 'commands', 'openspec');
1118
- await fs.mkdir(legacyCommandDir, { recursive: true });
1119
- await fs.writeFile(
1120
- path.join(legacyCommandDir, 'proposal.md'),
1121
- 'old command content'
1122
- );
1123
-
1124
- const consoleSpy = vi.spyOn(console, 'log');
1125
-
1126
- // Create update command with force option
1127
- const forceUpdateCommand = new UpdateCommand({ force: true });
1128
- await forceUpdateCommand.execute(testDir);
1129
-
1130
- // Should show detected tools message
1131
- expect(consoleSpy).toHaveBeenCalledWith(
1132
- expect.stringContaining('Tools detected from legacy artifacts')
1133
- );
1134
-
1135
- // Should show Claude Code being set up
1136
- expect(consoleSpy).toHaveBeenCalledWith(
1137
- expect.stringContaining('Claude Code')
1138
- );
1139
-
1140
- // Should show getting started message for newly configured tools
1141
- expect(consoleSpy).toHaveBeenCalledWith(
1142
- expect.stringContaining('Getting started')
1143
- );
1144
- expect(consoleSpy).toHaveBeenCalledWith(
1145
- expect.stringContaining('/opsx:new')
1146
- );
1147
-
1148
- // Skills should be created
1149
- const skillFile = path.join(testDir, '.claude', 'skills', 'openspec-explore', 'SKILL.md');
1150
- const skillExists = await FileSystemUtils.fileExists(skillFile);
1151
- expect(skillExists).toBe(true);
1152
-
1153
- // Legacy directory should be deleted
1154
- const legacyDirExists = await FileSystemUtils.directoryExists(legacyCommandDir);
1155
- expect(legacyDirExists).toBe(false);
1156
-
1157
- consoleSpy.mockRestore();
1158
- });
1159
-
1160
- it('should upgrade multiple legacy tools with --force', async () => {
1161
- // Create legacy command directories for Claude and Cursor
1162
- await fs.mkdir(path.join(testDir, '.claude', 'commands', 'openspec'), { recursive: true });
1163
- await fs.writeFile(
1164
- path.join(testDir, '.claude', 'commands', 'openspec', 'proposal.md'),
1165
- 'content'
1166
- );
1167
-
1168
- await fs.mkdir(path.join(testDir, '.cursor', 'commands'), { recursive: true });
1169
- await fs.writeFile(
1170
- path.join(testDir, '.cursor', 'commands', 'openspec-proposal.md'),
1171
- 'content'
1172
- );
1173
-
1174
- const consoleSpy = vi.spyOn(console, 'log');
1175
-
1176
- // Create update command with force option
1177
- const forceUpdateCommand = new UpdateCommand({ force: true });
1178
- await forceUpdateCommand.execute(testDir);
1179
-
1180
- // Should detect both tools
1181
- expect(consoleSpy).toHaveBeenCalledWith(
1182
- expect.stringContaining('Tools detected from legacy artifacts')
1183
- );
1184
-
1185
- // Both tools should have skills created
1186
- const claudeSkillFile = path.join(testDir, '.claude', 'skills', 'openspec-explore', 'SKILL.md');
1187
- const cursorSkillFile = path.join(testDir, '.cursor', 'skills', 'openspec-explore', 'SKILL.md');
1188
-
1189
- expect(await FileSystemUtils.fileExists(claudeSkillFile)).toBe(true);
1190
- expect(await FileSystemUtils.fileExists(cursorSkillFile)).toBe(true);
1191
-
1192
- consoleSpy.mockRestore();
1193
- });
1194
-
1195
- it('should not upgrade legacy tools already configured', async () => {
1196
- // Set up a configured Claude tool with skills
1197
- const skillsDir = path.join(testDir, '.claude', 'skills');
1198
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), { recursive: true });
1199
- await fs.writeFile(
1200
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
1201
- 'existing skill'
1202
- );
1203
-
1204
- // Also create legacy directory (simulating partial upgrade)
1205
- const legacyCommandDir = path.join(testDir, '.claude', 'commands', 'openspec');
1206
- await fs.mkdir(legacyCommandDir, { recursive: true });
1207
- await fs.writeFile(
1208
- path.join(legacyCommandDir, 'proposal.md'),
1209
- 'old command'
1210
- );
1211
-
1212
- const consoleSpy = vi.spyOn(console, 'log');
1213
-
1214
- // Create update command with force option
1215
- const forceUpdateCommand = new UpdateCommand({ force: true });
1216
- await forceUpdateCommand.execute(testDir);
1217
-
1218
- // Legacy cleanup should happen
1219
- expect(consoleSpy).toHaveBeenCalledWith(
1220
- expect.stringContaining('Removed .claude/commands/openspec/')
1221
- );
1222
-
1223
- // Should NOT show "Tools detected from legacy artifacts" because claude is already configured
1224
- const calls = consoleSpy.mock.calls.map(call =>
1225
- call.map(arg => String(arg)).join(' ')
1226
- );
1227
- const hasDetectedMessage = calls.some(call =>
1228
- call.includes('Tools detected from legacy artifacts')
1229
- );
1230
- expect(hasDetectedMessage).toBe(false);
1231
-
1232
- // Should update existing skills (not "Getting started" for newly configured)
1233
- expect(consoleSpy).toHaveBeenCalledWith(
1234
- expect.stringContaining('Updated: Claude Code')
1235
- );
1236
-
1237
- consoleSpy.mockRestore();
1238
- });
1239
-
1240
- it('should upgrade only unconfigured legacy tools when mixed', async () => {
1241
- // Set up configured Claude tool with skills
1242
- const claudeSkillsDir = path.join(testDir, '.claude', 'skills');
1243
- await fs.mkdir(path.join(claudeSkillsDir, 'openspec-explore'), { recursive: true });
1244
- await fs.writeFile(
1245
- path.join(claudeSkillsDir, 'openspec-explore', 'SKILL.md'),
1246
- 'existing skill'
1247
- );
1248
-
1249
- // Create legacy commands for both Claude (configured) and Cursor (not configured)
1250
- await fs.mkdir(path.join(testDir, '.claude', 'commands', 'openspec'), { recursive: true });
1251
- await fs.writeFile(
1252
- path.join(testDir, '.claude', 'commands', 'openspec', 'proposal.md'),
1253
- 'content'
1254
- );
1255
-
1256
- await fs.mkdir(path.join(testDir, '.cursor', 'commands'), { recursive: true });
1257
- await fs.writeFile(
1258
- path.join(testDir, '.cursor', 'commands', 'openspec-proposal.md'),
1259
- 'content'
1260
- );
1261
-
1262
- const consoleSpy = vi.spyOn(console, 'log');
1263
-
1264
- // Create update command with force option
1265
- const forceUpdateCommand = new UpdateCommand({ force: true });
1266
- await forceUpdateCommand.execute(testDir);
1267
-
1268
- // Should detect Cursor as a legacy tool to upgrade (but not Claude)
1269
- expect(consoleSpy).toHaveBeenCalledWith(
1270
- expect.stringContaining('Tools detected from legacy artifacts')
1271
- );
1272
-
1273
- // Cursor skills should be created
1274
- const cursorSkillFile = path.join(testDir, '.cursor', 'skills', 'openspec-explore', 'SKILL.md');
1275
- expect(await FileSystemUtils.fileExists(cursorSkillFile)).toBe(true);
1276
-
1277
- // Should show "Getting started" for newly configured Cursor
1278
- expect(consoleSpy).toHaveBeenCalledWith(
1279
- expect.stringContaining('Getting started')
1280
- );
1281
-
1282
- consoleSpy.mockRestore();
1283
- });
1284
-
1285
- it('should not show getting started message when no new tools configured', async () => {
1286
- // Set up a configured tool (no legacy artifacts)
1287
- const skillsDir = path.join(testDir, '.claude', 'skills');
1288
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), { recursive: true });
1289
- await fs.writeFile(
1290
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
1291
- 'old skill'
1292
- );
1293
-
1294
- const consoleSpy = vi.spyOn(console, 'log');
1295
-
1296
- await updateCommand.execute(testDir);
1297
-
1298
- // Should NOT show "Getting started" message
1299
- const calls = consoleSpy.mock.calls.map(call =>
1300
- call.map(arg => String(arg)).join(' ')
1301
- );
1302
- const hasGettingStarted = calls.some(call =>
1303
- call.includes('Getting started')
1304
- );
1305
- expect(hasGettingStarted).toBe(false);
1306
-
1307
- consoleSpy.mockRestore();
1308
- });
1309
-
1310
- it('should create only effective profile skills when upgrading legacy tools', async () => {
1311
- // Create legacy command directory
1312
- await fs.mkdir(path.join(testDir, '.claude', 'commands', 'openspec'), { recursive: true });
1313
- await fs.writeFile(
1314
- path.join(testDir, '.claude', 'commands', 'openspec', 'proposal.md'),
1315
- 'content'
1316
- );
1317
-
1318
- // Create update command with force option
1319
- const forceUpdateCommand = new UpdateCommand({ force: true });
1320
- await forceUpdateCommand.execute(testDir);
1321
-
1322
- // Default profile is core, so only core workflows should be generated.
1323
- const skillNames = [
1324
- 'openspec-propose',
1325
- 'openspec-explore',
1326
- 'openspec-apply-change',
1327
- 'openspec-sync-specs',
1328
- 'openspec-archive-change',
1329
- ];
1330
-
1331
- const skillsDir = path.join(testDir, '.claude', 'skills');
1332
- for (const skillName of skillNames) {
1333
- const skillFile = path.join(skillsDir, skillName, 'SKILL.md');
1334
- const exists = await FileSystemUtils.fileExists(skillFile);
1335
- expect(exists).toBe(true);
1336
- }
1337
-
1338
- const nonCoreSkill = path.join(skillsDir, 'openspec-new-change', 'SKILL.md');
1339
- expect(await FileSystemUtils.fileExists(nonCoreSkill)).toBe(false);
1340
- });
1341
-
1342
- it('should create commands when upgrading legacy tools', async () => {
1343
- // Create legacy command directory
1344
- await fs.mkdir(path.join(testDir, '.claude', 'commands', 'openspec'), { recursive: true });
1345
- await fs.writeFile(
1346
- path.join(testDir, '.claude', 'commands', 'openspec', 'proposal.md'),
1347
- 'content'
1348
- );
1349
-
1350
- // Create update command with force option
1351
- const forceUpdateCommand = new UpdateCommand({ force: true });
1352
- await forceUpdateCommand.execute(testDir);
1353
-
1354
- // New opsx commands should be created
1355
- const commandsDir = path.join(testDir, '.claude', 'commands', 'opsx');
1356
- const exploreCmd = path.join(commandsDir, 'explore.md');
1357
- const exists = await FileSystemUtils.fileExists(exploreCmd);
1358
- expect(exists).toBe(true);
1359
- });
1360
-
1361
- it('should not inject non-profile workflows when upgrading legacy tools', async () => {
1362
- setMockConfig({
1363
- featureFlags: {},
1364
- profile: 'custom',
1365
- delivery: 'both',
1366
- workflows: ['explore'],
1367
- });
1368
-
1369
- await fs.mkdir(path.join(testDir, '.claude', 'commands', 'openspec'), { recursive: true });
1370
- await fs.writeFile(
1371
- path.join(testDir, '.claude', 'commands', 'openspec', 'proposal.md'),
1372
- 'content'
1373
- );
1374
-
1375
- const forceUpdateCommand = new UpdateCommand({ force: true });
1376
- await forceUpdateCommand.execute(testDir);
1377
-
1378
- const skillsDir = path.join(testDir, '.claude', 'skills');
1379
- expect(await FileSystemUtils.fileExists(
1380
- path.join(skillsDir, 'openspec-explore', 'SKILL.md')
1381
- )).toBe(true);
1382
- expect(await FileSystemUtils.fileExists(
1383
- path.join(skillsDir, 'openspec-propose', 'SKILL.md')
1384
- )).toBe(false);
1385
-
1386
- const commandsDir = path.join(testDir, '.claude', 'commands', 'opsx');
1387
- expect(await FileSystemUtils.fileExists(
1388
- path.join(commandsDir, 'explore.md')
1389
- )).toBe(true);
1390
- expect(await FileSystemUtils.fileExists(
1391
- path.join(commandsDir, 'propose.md')
1392
- )).toBe(false);
1393
- });
1394
- });
1395
-
1396
- describe('profile-aware updates', () => {
1397
- it('should generate only profile workflows when custom profile is set', async () => {
1398
- // Set custom profile with only explore and new
1399
- setMockConfig({
1400
- featureFlags: {},
1401
- profile: 'custom',
1402
- delivery: 'both',
1403
- workflows: ['explore', 'new'],
1404
- });
1405
-
1406
- // Set up a configured tool
1407
- const skillsDir = path.join(testDir, '.claude', 'skills');
1408
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), { recursive: true });
1409
- await fs.writeFile(path.join(skillsDir, 'openspec-explore', 'SKILL.md'), 'old');
1410
-
1411
- await updateCommand.execute(testDir);
1412
-
1413
- // Should create explore and new skills
1414
- expect(await FileSystemUtils.fileExists(
1415
- path.join(skillsDir, 'openspec-explore', 'SKILL.md')
1416
- )).toBe(true);
1417
- expect(await FileSystemUtils.fileExists(
1418
- path.join(skillsDir, 'openspec-new-change', 'SKILL.md')
1419
- )).toBe(true);
1420
-
1421
- // Should NOT create non-profile skills
1422
- expect(await FileSystemUtils.fileExists(
1423
- path.join(skillsDir, 'openspec-apply-change', 'SKILL.md')
1424
- )).toBe(false);
1425
- expect(await FileSystemUtils.fileExists(
1426
- path.join(skillsDir, 'openspec-propose', 'SKILL.md')
1427
- )).toBe(false);
1428
- });
1429
-
1430
- it('should suggest core preset when custom profile preserves the old core workflow set', async () => {
1431
- setMockConfig({
1432
- featureFlags: {},
1433
- profile: 'custom',
1434
- delivery: 'both',
1435
- workflows: ['propose', 'explore', 'apply', 'archive'],
1436
- });
1437
-
1438
- const initCommand = new InitCommand({ tools: 'claude', force: true });
1439
- await initCommand.execute(testDir);
1440
-
1441
- const consoleSpy = vi.spyOn(console, 'log');
1442
-
1443
- await updateCommand.execute(testDir);
1444
-
1445
- const calls = consoleSpy.mock.calls.map(call =>
1446
- call.map(arg => String(arg)).join(' ')
1447
- );
1448
- expect(calls.some(call =>
1449
- call.includes('The core profile now includes sync')
1450
- )).toBe(true);
1451
- expect(calls.some(call =>
1452
- call.includes('openspec config profile core') && call.includes('openspec update')
1453
- )).toBe(true);
1454
-
1455
- expect(await FileSystemUtils.fileExists(
1456
- path.join(testDir, '.claude', 'skills', 'openspec-sync-specs', 'SKILL.md')
1457
- )).toBe(false);
1458
- expect(await FileSystemUtils.fileExists(
1459
- path.join(testDir, '.claude', 'commands', 'opsx', 'sync.md')
1460
- )).toBe(false);
1461
-
1462
- consoleSpy.mockRestore();
1463
- });
1464
-
1465
- it('should respect skills-only delivery setting', async () => {
1466
- setMockConfig({
1467
- featureFlags: {},
1468
- profile: 'core',
1469
- delivery: 'skills',
1470
- });
1471
-
1472
- const skillsDir = path.join(testDir, '.claude', 'skills');
1473
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), { recursive: true });
1474
- await fs.writeFile(path.join(skillsDir, 'openspec-explore', 'SKILL.md'), 'old');
1475
-
1476
- await updateCommand.execute(testDir);
1477
-
1478
- // Skills should be created
1479
- expect(await FileSystemUtils.fileExists(
1480
- path.join(skillsDir, 'openspec-explore', 'SKILL.md')
1481
- )).toBe(true);
1482
-
1483
- // Commands should NOT be created
1484
- const commandsDir = path.join(testDir, '.claude', 'commands', 'opsx');
1485
- expect(await FileSystemUtils.fileExists(
1486
- path.join(commandsDir, 'explore.md')
1487
- )).toBe(false);
1488
- });
1489
-
1490
- it('should respect commands-only delivery setting', async () => {
1491
- setMockConfig({
1492
- featureFlags: {},
1493
- profile: 'core',
1494
- delivery: 'commands',
1495
- });
1496
-
1497
- const skillsDir = path.join(testDir, '.claude', 'skills');
1498
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), { recursive: true });
1499
- await fs.writeFile(path.join(skillsDir, 'openspec-explore', 'SKILL.md'), 'old');
1500
-
1501
- await updateCommand.execute(testDir);
1502
-
1503
- // Commands should be created
1504
- const commandsDir = path.join(testDir, '.claude', 'commands', 'opsx');
1505
- expect(await FileSystemUtils.fileExists(
1506
- path.join(commandsDir, 'explore.md')
1507
- )).toBe(true);
1508
-
1509
- // Skills should be removed for commands-only delivery
1510
- expect(await FileSystemUtils.fileExists(
1511
- path.join(skillsDir, 'openspec-explore', 'SKILL.md')
1512
- )).toBe(false);
1513
- });
1514
-
1515
- it('should remove skills for configured tools without command adapters in commands-only delivery', async () => {
1516
- setMockConfig({
1517
- featureFlags: {},
1518
- profile: 'core',
1519
- delivery: 'commands',
1520
- });
1521
-
1522
- const { AI_TOOLS } = await import('../../src/core/config.js');
1523
- const { CommandAdapterRegistry } = await import('../../src/core/command-generation/index.js');
1524
- const adapterlessTool = AI_TOOLS.find((tool) => tool.skillsDir && !CommandAdapterRegistry.get(tool.value));
1525
- expect(adapterlessTool).toBeDefined();
1526
- if (!adapterlessTool?.skillsDir) {
1527
- return;
1528
- }
1529
-
1530
- const skillsDir = path.join(testDir, adapterlessTool.skillsDir, 'skills');
1531
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), { recursive: true });
1532
- await fs.writeFile(path.join(skillsDir, 'openspec-explore', 'SKILL.md'), 'old');
1533
-
1534
- await expect(updateCommand.execute(testDir)).resolves.toBeUndefined();
1535
-
1536
- expect(await FileSystemUtils.fileExists(
1537
- path.join(skillsDir, 'openspec-explore', 'SKILL.md')
1538
- )).toBe(false);
1539
- });
1540
-
1541
- it('should apply config sync when templates are up to date', async () => {
1542
- setMockConfig({
1543
- featureFlags: {},
1544
- profile: 'core',
1545
- delivery: 'skills',
1546
- });
1547
-
1548
- const skillsDir = path.join(testDir, '.claude', 'skills');
1549
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), { recursive: true });
1550
- const packageJsonPath = path.join(process.cwd(), 'package.json');
1551
- const packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8')) as { version: string };
1552
- await fs.writeFile(
1553
- path.join(skillsDir, 'openspec-explore', 'SKILL.md'),
1554
- `---
1555
- name: openspec-explore
1556
- metadata:
1557
- generatedBy: "${packageJson.version}"
1558
- ---
1559
- content
1560
- `
1561
- );
1562
-
1563
- const commandsDir = path.join(testDir, '.claude', 'commands', 'opsx');
1564
- await fs.mkdir(commandsDir, { recursive: true });
1565
- await fs.writeFile(path.join(commandsDir, 'explore.md'), 'old command');
1566
-
1567
- await updateCommand.execute(testDir);
1568
-
1569
- // Command files should be removed due to delivery change, even though skill version is current
1570
- expect(await FileSystemUtils.fileExists(
1571
- path.join(commandsDir, 'explore.md')
1572
- )).toBe(false);
1573
- });
1574
-
1575
- it('should detect commands-only tool configuration', async () => {
1576
- setMockConfig({
1577
- featureFlags: {},
1578
- profile: 'core',
1579
- delivery: 'commands',
1580
- });
1581
-
1582
- const commandsDir = path.join(testDir, '.claude', 'commands', 'opsx');
1583
- await fs.mkdir(commandsDir, { recursive: true });
1584
- await fs.writeFile(path.join(commandsDir, 'explore.md'), 'existing command');
1585
-
1586
- const consoleSpy = vi.spyOn(console, 'log');
1587
-
1588
- await updateCommand.execute(testDir);
1589
-
1590
- // Should not short-circuit with "No configured tools found"
1591
- const calls = consoleSpy.mock.calls.map(call =>
1592
- call.map(arg => String(arg)).join(' ')
1593
- );
1594
- const hasNoConfiguredMessage = calls.some(call =>
1595
- call.includes('No configured tools found')
1596
- );
1597
- expect(hasNoConfiguredMessage).toBe(false);
1598
-
1599
- // Commands should be updated/generated for the core profile
1600
- expect(await FileSystemUtils.fileExists(
1601
- path.join(commandsDir, 'propose.md')
1602
- )).toBe(true);
1603
-
1604
- consoleSpy.mockRestore();
1605
- });
1606
-
1607
- it('should remove workflows outside profile during update sync', async () => {
1608
- // Set core profile (propose, explore, apply, sync, archive)
1609
- setMockConfig({
1610
- featureFlags: {},
1611
- profile: 'core',
1612
- delivery: 'both',
1613
- });
1614
-
1615
- // Set up tool with extra workflows beyond core profile
1616
- const skillsDir = path.join(testDir, '.claude', 'skills');
1617
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), { recursive: true });
1618
- await fs.writeFile(path.join(skillsDir, 'openspec-explore', 'SKILL.md'), 'old');
1619
-
1620
- // Add a non-core workflow
1621
- await fs.mkdir(path.join(skillsDir, 'openspec-new-change'), { recursive: true });
1622
- await fs.writeFile(path.join(skillsDir, 'openspec-new-change', 'SKILL.md'), 'old');
1623
- const extraCommandFile = path.join(testDir, '.claude', 'commands', 'opsx', 'new.md');
1624
- await fs.mkdir(path.dirname(extraCommandFile), { recursive: true });
1625
- await fs.writeFile(extraCommandFile, 'old');
1626
-
1627
- const consoleSpy = vi.spyOn(console, 'log');
1628
-
1629
- await updateCommand.execute(testDir);
1630
-
1631
- // Deselected workflow artifacts should be removed for both delivery surfaces.
1632
- expect(await FileSystemUtils.fileExists(
1633
- path.join(skillsDir, 'openspec-new-change', 'SKILL.md')
1634
- )).toBe(false);
1635
- expect(await FileSystemUtils.fileExists(extraCommandFile)).toBe(false);
1636
-
1637
- // Should report deselected workflow cleanup.
1638
- const calls = consoleSpy.mock.calls.map(call =>
1639
- call.map(arg => String(arg)).join(' ')
1640
- );
1641
- const hasDeselectedRemovalNote = calls.some(call =>
1642
- call.includes('deselected workflows')
1643
- );
1644
- expect(hasDeselectedRemovalNote).toBe(true);
1645
-
1646
- consoleSpy.mockRestore();
1647
- });
1648
- });
1649
-
1650
- describe('new tool detection', () => {
1651
- it('should detect new tool directories not currently configured', async () => {
1652
- // Set up a configured Claude tool
1653
- const claudeSkillsDir = path.join(testDir, '.claude', 'skills');
1654
- await fs.mkdir(path.join(claudeSkillsDir, 'openspec-explore'), { recursive: true });
1655
- await fs.writeFile(path.join(claudeSkillsDir, 'openspec-explore', 'SKILL.md'), 'old');
1656
-
1657
- // Create a Cursor directory (not configured — no skills)
1658
- await fs.mkdir(path.join(testDir, '.cursor'), { recursive: true });
1659
-
1660
- const consoleSpy = vi.spyOn(console, 'log');
1661
-
1662
- await updateCommand.execute(testDir);
1663
-
1664
- // Should detect Cursor as a new tool
1665
- const calls = consoleSpy.mock.calls.map(call =>
1666
- call.map(arg => String(arg)).join(' ')
1667
- );
1668
- const hasNewToolMessage = calls.some(call =>
1669
- call.includes("Detected new tool: Cursor. Run 'openspec init' to add it.")
1670
- );
1671
- expect(hasNewToolMessage).toBe(true);
1672
-
1673
- consoleSpy.mockRestore();
1674
- });
1675
-
1676
- it('should consolidate multiple new tools into one message', async () => {
1677
- // Set up a configured Claude tool
1678
- const claudeSkillsDir = path.join(testDir, '.claude', 'skills');
1679
- await fs.mkdir(path.join(claudeSkillsDir, 'openspec-explore'), { recursive: true });
1680
- await fs.writeFile(path.join(claudeSkillsDir, 'openspec-explore', 'SKILL.md'), 'old');
1681
-
1682
- // Create two unconfigured tool directories
1683
- await fs.mkdir(path.join(testDir, '.github'), { recursive: true });
1684
- await fs.writeFile(path.join(testDir, '.github', 'copilot-instructions.md'), '');
1685
- await fs.mkdir(path.join(testDir, '.windsurf'), { recursive: true });
1686
-
1687
- const consoleSpy = vi.spyOn(console, 'log');
1688
-
1689
- await updateCommand.execute(testDir);
1690
-
1691
- const calls = consoleSpy.mock.calls.map(call =>
1692
- call.map(arg => String(arg)).join(' ')
1693
- );
1694
-
1695
- const consolidatedCalls = calls.filter(call =>
1696
- call.includes('Detected new tools:')
1697
- );
1698
- expect(consolidatedCalls).toHaveLength(1);
1699
- expect(consolidatedCalls[0]).toContain('GitHub Copilot');
1700
- expect(consolidatedCalls[0]).toContain('Windsurf');
1701
- expect(consolidatedCalls[0]).toContain("Run 'openspec init' to add them.");
1702
-
1703
- const repeatedSingularCalls = calls.filter(call =>
1704
- call.includes('Detected new tool:')
1705
- );
1706
- expect(repeatedSingularCalls).toHaveLength(0);
1707
-
1708
- consoleSpy.mockRestore();
1709
- });
1710
-
1711
- it('should not show new tool message when no new tools detected', async () => {
1712
- // Set up a configured tool (only Claude, no other tool directories)
1713
- const skillsDir = path.join(testDir, '.claude', 'skills');
1714
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), { recursive: true });
1715
- await fs.writeFile(path.join(skillsDir, 'openspec-explore', 'SKILL.md'), 'old');
1716
-
1717
- const consoleSpy = vi.spyOn(console, 'log');
1718
-
1719
- await updateCommand.execute(testDir);
1720
-
1721
- const calls = consoleSpy.mock.calls.map(call =>
1722
- call.map(arg => String(arg)).join(' ')
1723
- );
1724
- const hasNewToolMessage = calls.some(call =>
1725
- call.includes('Detected new tool')
1726
- );
1727
- expect(hasNewToolMessage).toBe(false);
1728
-
1729
- consoleSpy.mockRestore();
1730
- });
1731
- });
1732
-
1733
- describe('scanInstalledWorkflows', () => {
1734
- it('should detect installed workflows across tools', async () => {
1735
- // Create skills for Claude
1736
- const claudeSkillsDir = path.join(testDir, '.claude', 'skills');
1737
- await fs.mkdir(path.join(claudeSkillsDir, 'openspec-explore'), { recursive: true });
1738
- await fs.writeFile(path.join(claudeSkillsDir, 'openspec-explore', 'SKILL.md'), 'content');
1739
- await fs.mkdir(path.join(claudeSkillsDir, 'openspec-apply-change'), { recursive: true });
1740
- await fs.writeFile(path.join(claudeSkillsDir, 'openspec-apply-change', 'SKILL.md'), 'content');
1741
-
1742
- const workflows = scanInstalledWorkflows(testDir, ['claude']);
1743
- expect(workflows).toContain('explore');
1744
- expect(workflows).toContain('apply');
1745
- expect(workflows).not.toContain('propose');
1746
- });
1747
-
1748
- it('should return union of workflows across multiple tools', async () => {
1749
- // Claude has explore
1750
- const claudeSkillsDir = path.join(testDir, '.claude', 'skills');
1751
- await fs.mkdir(path.join(claudeSkillsDir, 'openspec-explore'), { recursive: true });
1752
- await fs.writeFile(path.join(claudeSkillsDir, 'openspec-explore', 'SKILL.md'), 'content');
1753
-
1754
- // Cursor has apply
1755
- const cursorSkillsDir = path.join(testDir, '.cursor', 'skills');
1756
- await fs.mkdir(path.join(cursorSkillsDir, 'openspec-apply-change'), { recursive: true });
1757
- await fs.writeFile(path.join(cursorSkillsDir, 'openspec-apply-change', 'SKILL.md'), 'content');
1758
-
1759
- const workflows = scanInstalledWorkflows(testDir, ['claude', 'cursor']);
1760
- expect(workflows).toContain('explore');
1761
- expect(workflows).toContain('apply');
1762
- });
1763
-
1764
- it('should only match workflows in ALL_WORKFLOWS', async () => {
1765
- // Create a custom skill directory that doesn't match any workflow
1766
- const skillsDir = path.join(testDir, '.claude', 'skills');
1767
- await fs.mkdir(path.join(skillsDir, 'my-custom-skill'), { recursive: true });
1768
- await fs.writeFile(path.join(skillsDir, 'my-custom-skill', 'SKILL.md'), 'content');
1769
-
1770
- const workflows = scanInstalledWorkflows(testDir, ['claude']);
1771
- expect(workflows).toHaveLength(0);
1772
- });
1773
-
1774
- it('should return empty array when no tools have skills', async () => {
1775
- const workflows = scanInstalledWorkflows(testDir, ['claude']);
1776
- expect(workflows).toHaveLength(0);
1777
- });
1778
-
1779
- it('should detect installed workflows from managed command files', async () => {
1780
- const commandsDir = path.join(testDir, '.claude', 'commands', 'opsx');
1781
- await fs.mkdir(commandsDir, { recursive: true });
1782
- await fs.writeFile(path.join(commandsDir, 'explore.md'), 'content');
1783
-
1784
- const workflows = scanInstalledWorkflows(testDir, ['claude']);
1785
- expect(workflows).toContain('explore');
1786
- });
1787
- });
1788
-
1789
- describe('tools output', () => {
1790
- it('should list affected tools in output', async () => {
1791
- const skillsDir = path.join(testDir, '.claude', 'skills');
1792
- await fs.mkdir(path.join(skillsDir, 'openspec-explore'), { recursive: true });
1793
- await fs.writeFile(path.join(skillsDir, 'openspec-explore', 'SKILL.md'), 'old');
1794
-
1795
- const consoleSpy = vi.spyOn(console, 'log');
1796
-
1797
- await updateCommand.execute(testDir);
1798
-
1799
- const calls = consoleSpy.mock.calls.map(call =>
1800
- call.map(arg => String(arg)).join(' ')
1801
- );
1802
- const hasToolsList = calls.some(call =>
1803
- call.includes('Tools:') && call.includes('Claude Code')
1804
- );
1805
- expect(hasToolsList).toBe(true);
1806
-
1807
- consoleSpy.mockRestore();
1808
- });
1809
- });
1810
- });