specify-cli 1.0.3__tar.gz → 1.0.4__tar.gz

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 (550) hide show
  1. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/ISSUE_TEMPLATE/agent_request.yml +1 -1
  2. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/ISSUE_TEMPLATE/bug_report.yml +1 -0
  3. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/ISSUE_TEMPLATE/feature_request.yml +1 -0
  4. {specify_cli-1.0.3 → specify_cli-1.0.4}/AGENTS.md +1 -1
  5. {specify_cli-1.0.3 → specify_cli-1.0.4}/CHANGELOG.md +25 -0
  6. {specify_cli-1.0.3 → specify_cli-1.0.4}/PKG-INFO +1 -1
  7. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/community/extensions.md +1 -1
  8. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/extensions.md +2 -0
  9. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/integrations.md +1 -0
  10. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/catalog.community.json +9 -9
  11. {specify_cli-1.0.3 → specify_cli-1.0.4}/integrations/catalog.json +10 -1
  12. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/PUBLISHING.md +37 -0
  13. {specify_cli-1.0.3 → specify_cli-1.0.4}/pyproject.toml +1 -1
  14. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/bash/common.sh +13 -5
  15. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/powershell/create-new-feature.ps1 +8 -1
  16. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_invocation_style.py +1 -1
  17. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/authentication/config.py +4 -1
  18. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/models/catalog.py +11 -0
  19. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/models/records.py +12 -6
  20. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/commands/init.py +7 -0
  21. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/extensions/_commands.py +109 -13
  22. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/__init__.py +2 -0
  23. specify_cli-1.0.4/src/specify_cli/integrations/dsh/__init__.py +64 -0
  24. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/rovodev/__init__.py +11 -0
  25. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/presets/__init__.py +280 -1
  26. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/presets/_commands.py +112 -0
  27. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/_commands.py +3 -3
  28. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/catalog.py +4 -2
  29. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/expressions.py +34 -1
  30. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/overlays/_commands.py +18 -2
  31. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/overlays/schema.py +7 -1
  32. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/contract/test_catalog_schema.py +17 -0
  33. specify_cli-1.0.4/tests/integrations/test_integration_dsh.py +314 -0
  34. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_rovodev.py +39 -0
  35. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_registry.py +1 -1
  36. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/parity_helpers.py +11 -1
  37. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_agent_config_consistency.py +1 -0
  38. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_authentication.py +1 -1
  39. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_create_new_feature_python_parity.py +53 -0
  40. specify_cli-1.0.4/tests/test_extension_content_staleness.py +134 -0
  41. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_extensions.py +206 -0
  42. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_presets.py +591 -0
  43. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_resolve_template_python_parity.py +34 -0
  44. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_workflows.py +150 -0
  45. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_records.py +70 -0
  46. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/workflows/test_overlay_commands.py +109 -0
  47. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/workflows/test_overlay_schema.py +51 -0
  48. {specify_cli-1.0.3 → specify_cli-1.0.4}/.devcontainer/devcontainer.json +0 -0
  49. {specify_cli-1.0.3 → specify_cli-1.0.4}/.devcontainer/post-create.sh +0 -0
  50. {specify_cli-1.0.3 → specify_cli-1.0.4}/.editorconfig +0 -0
  51. {specify_cli-1.0.3 → specify_cli-1.0.4}/.gitattributes +0 -0
  52. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/CODEOWNERS +0 -0
  53. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/ISSUE_TEMPLATE/bundle_submission.yml +0 -0
  54. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  55. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/ISSUE_TEMPLATE/extension_submission.yml +0 -0
  56. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/ISSUE_TEMPLATE/preset_submission.yml +0 -0
  57. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  58. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/aw/actions-lock.json +0 -0
  59. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/dependabot.yml +0 -0
  60. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/scripts/check_security_requirements.py +0 -0
  61. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/security-audit-requirements.txt +0 -0
  62. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/skills/add-community-extension/SKILL.md +0 -0
  63. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/RELEASE-PROCESS.md +0 -0
  64. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/add-community-bundle.lock.yml +0 -0
  65. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/add-community-bundle.md +0 -0
  66. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/add-community-extension.lock.yml +0 -0
  67. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/add-community-extension.md +0 -0
  68. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/add-community-preset.lock.yml +0 -0
  69. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/add-community-preset.md +0 -0
  70. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/bug-assess.lock.yml +0 -0
  71. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/bug-assess.md +0 -0
  72. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/bug-fix.lock.yml +0 -0
  73. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/bug-fix.md +0 -0
  74. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/bug-test.lock.yml +0 -0
  75. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/bug-test.md +0 -0
  76. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/catalog-assign.yml +0 -0
  77. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/codeql.yml +0 -0
  78. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/docs.yml +0 -0
  79. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/feature-assess.lock.yml +0 -0
  80. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/feature-assess.md +0 -0
  81. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/lint.yml +0 -0
  82. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/publish-pypi.yml +0 -0
  83. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/release-trigger.yml +0 -0
  84. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/release.yml +0 -0
  85. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/security.yml +0 -0
  86. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/stale.yml +0 -0
  87. {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/test.yml +0 -0
  88. {specify_cli-1.0.3 → specify_cli-1.0.4}/.gitignore +0 -0
  89. {specify_cli-1.0.3 → specify_cli-1.0.4}/.markdownlint-cli2.jsonc +0 -0
  90. {specify_cli-1.0.3 → specify_cli-1.0.4}/.pre-commit-config.yaml +0 -0
  91. {specify_cli-1.0.3 → specify_cli-1.0.4}/.zenodo.json +0 -0
  92. {specify_cli-1.0.3 → specify_cli-1.0.4}/CITATION.cff +0 -0
  93. {specify_cli-1.0.3 → specify_cli-1.0.4}/CODE_OF_CONDUCT.md +0 -0
  94. {specify_cli-1.0.3 → specify_cli-1.0.4}/CONTRIBUTING.md +0 -0
  95. {specify_cli-1.0.3 → specify_cli-1.0.4}/DEVELOPMENT.md +0 -0
  96. {specify_cli-1.0.3 → specify_cli-1.0.4}/LICENSE +0 -0
  97. {specify_cli-1.0.3 → specify_cli-1.0.4}/README.md +0 -0
  98. {specify_cli-1.0.3 → specify_cli-1.0.4}/README.zh-CN.md +0 -0
  99. {specify_cli-1.0.3 → specify_cli-1.0.4}/SECURITY.md +0 -0
  100. {specify_cli-1.0.3 → specify_cli-1.0.4}/SUPPORT.md +0 -0
  101. {specify_cli-1.0.3 → specify_cli-1.0.4}/bundles/catalog.community.json +0 -0
  102. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/.gitignore +0 -0
  103. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/README.md +0 -0
  104. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/community/bundles.md +0 -0
  105. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/community/friends.md +0 -0
  106. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/community/overview.md +0 -0
  107. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/community/presets.md +0 -0
  108. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/community/walkthroughs.md +0 -0
  109. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/concepts/complex-features.md +0 -0
  110. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/concepts/sdd.md +0 -0
  111. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/concepts/spec-of-specs.md +0 -0
  112. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/concepts/spec-persistence.md +0 -0
  113. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/docfx.json +0 -0
  114. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/guides/evolving-specs.md +0 -0
  115. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/guides/existing-projects.md +0 -0
  116. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/guides/monorepo.md +0 -0
  117. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/history.md +0 -0
  118. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/images/spec-kit-logo.webp +0 -0
  119. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/index.md +0 -0
  120. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/install/air-gapped.md +0 -0
  121. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/install/one-time.md +0 -0
  122. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/install/pipx.md +0 -0
  123. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/install/pypi.md +0 -0
  124. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/install/uv.md +0 -0
  125. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/installation.md +0 -0
  126. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/local-development.md +0 -0
  127. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/quickstart.md +0 -0
  128. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/agentic-bugfix.md +0 -0
  129. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/agentic-sdd.md +0 -0
  130. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/authentication.md +0 -0
  131. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/bundles.md +0 -0
  132. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/core.md +0 -0
  133. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/overview.md +0 -0
  134. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/presets.md +0 -0
  135. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/workflows.md +0 -0
  136. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/template/public/main.css +0 -0
  137. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/toc.yml +0 -0
  138. {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/upgrade.md +0 -0
  139. {specify_cli-1.0.3 → specify_cli-1.0.4}/examples/bundles/business-analyst/README.md +0 -0
  140. {specify_cli-1.0.3 → specify_cli-1.0.4}/examples/bundles/business-analyst/bundle.yml +0 -0
  141. {specify_cli-1.0.3 → specify_cli-1.0.4}/examples/bundles/developer/README.md +0 -0
  142. {specify_cli-1.0.3 → specify_cli-1.0.4}/examples/bundles/developer/bundle.yml +0 -0
  143. {specify_cli-1.0.3 → specify_cli-1.0.4}/examples/bundles/product-manager/README.md +0 -0
  144. {specify_cli-1.0.3 → specify_cli-1.0.4}/examples/bundles/product-manager/bundle.yml +0 -0
  145. {specify_cli-1.0.3 → specify_cli-1.0.4}/examples/bundles/security-researcher/README.md +0 -0
  146. {specify_cli-1.0.3 → specify_cli-1.0.4}/examples/bundles/security-researcher/bundle.yml +0 -0
  147. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/EXTENSION-API-REFERENCE.md +0 -0
  148. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/EXTENSION-DEVELOPMENT-GUIDE.md +0 -0
  149. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/EXTENSION-PUBLISHING-GUIDE.md +0 -0
  150. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/EXTENSION-USER-GUIDE.md +0 -0
  151. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/README.md +0 -0
  152. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/RFC-EXTENSION-SYSTEM.md +0 -0
  153. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/agent-context/README.md +0 -0
  154. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/agent-context/agent-context-config.yml +0 -0
  155. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/agent-context/agent-context-defaults.json +0 -0
  156. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/agent-context/commands/speckit.agent-context.update.md +0 -0
  157. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/agent-context/extension.yml +0 -0
  158. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/agent-context/scripts/bash/update-agent-context.sh +0 -0
  159. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/agent-context/scripts/powershell/update-agent-context.ps1 +0 -0
  160. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/agent-context/scripts/python/update_agent_context.py +0 -0
  161. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/assess/README.md +0 -0
  162. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/assess/commands/speckit.assess.decide.md +0 -0
  163. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/assess/commands/speckit.assess.define.md +0 -0
  164. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/assess/commands/speckit.assess.intake.md +0 -0
  165. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/assess/commands/speckit.assess.research.md +0 -0
  166. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/assess/commands/speckit.assess.shape.md +0 -0
  167. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/assess/extension.yml +0 -0
  168. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/bug/README.md +0 -0
  169. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/bug/commands/speckit.bug.assess.md +0 -0
  170. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/bug/commands/speckit.bug.fix.md +0 -0
  171. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/bug/commands/speckit.bug.test.md +0 -0
  172. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/bug/extension.yml +0 -0
  173. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/catalog.json +0 -0
  174. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/README.md +0 -0
  175. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/commands/speckit.git.commit.md +0 -0
  176. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/commands/speckit.git.feature.md +0 -0
  177. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/commands/speckit.git.initialize.md +0 -0
  178. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/commands/speckit.git.remote.md +0 -0
  179. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/commands/speckit.git.validate.md +0 -0
  180. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/config-template.yml +0 -0
  181. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/extension.yml +0 -0
  182. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/git-config.yml +0 -0
  183. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/bash/auto-commit.sh +0 -0
  184. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/bash/create-new-feature-branch.sh +0 -0
  185. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/bash/git-common.sh +0 -0
  186. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/bash/initialize-repo.sh +0 -0
  187. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/powershell/auto-commit.ps1 +0 -0
  188. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/powershell/create-new-feature-branch.ps1 +0 -0
  189. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/powershell/git-common.ps1 +0 -0
  190. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/powershell/initialize-repo.ps1 +0 -0
  191. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/python/auto_commit.py +0 -0
  192. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/python/create_new_feature_branch.py +0 -0
  193. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/python/git_common.py +0 -0
  194. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/python/initialize_repo.py +0 -0
  195. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/selftest/commands/selftest.md +0 -0
  196. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/selftest/extension.yml +0 -0
  197. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/template/.gitignore +0 -0
  198. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/template/CHANGELOG.md +0 -0
  199. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/template/EXAMPLE-README.md +0 -0
  200. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/template/LICENSE +0 -0
  201. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/template/README.md +0 -0
  202. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/template/commands/example.md +0 -0
  203. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/template/config-template.yml +0 -0
  204. {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/template/extension.yml +0 -0
  205. {specify_cli-1.0.3 → specify_cli-1.0.4}/integrations/CONTRIBUTING.md +0 -0
  206. {specify_cli-1.0.3 → specify_cli-1.0.4}/integrations/README.md +0 -0
  207. {specify_cli-1.0.3 → specify_cli-1.0.4}/integrations/catalog.community.json +0 -0
  208. {specify_cli-1.0.3 → specify_cli-1.0.4}/media/bootstrap-claude-code.gif +0 -0
  209. {specify_cli-1.0.3 → specify_cli-1.0.4}/media/logo_large.webp +0 -0
  210. {specify_cli-1.0.3 → specify_cli-1.0.4}/media/logo_small.webp +0 -0
  211. {specify_cli-1.0.3 → specify_cli-1.0.4}/media/spec-kit-video-header.jpg +0 -0
  212. {specify_cli-1.0.3 → specify_cli-1.0.4}/media/specify_cli.gif +0 -0
  213. {specify_cli-1.0.3 → specify_cli-1.0.4}/newsletters/2026-April.md +0 -0
  214. {specify_cli-1.0.3 → specify_cli-1.0.4}/newsletters/2026-February.md +0 -0
  215. {specify_cli-1.0.3 → specify_cli-1.0.4}/newsletters/2026-July.md +0 -0
  216. {specify_cli-1.0.3 → specify_cli-1.0.4}/newsletters/2026-June.md +0 -0
  217. {specify_cli-1.0.3 → specify_cli-1.0.4}/newsletters/2026-March.md +0 -0
  218. {specify_cli-1.0.3 → specify_cli-1.0.4}/newsletters/2026-May.md +0 -0
  219. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/ARCHITECTURE.md +0 -0
  220. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/README.md +0 -0
  221. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/catalog.community.json +0 -0
  222. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/catalog.json +0 -0
  223. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/constitution-sync/README.md +0 -0
  224. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/constitution-sync/commands/speckit.constitution.md +0 -0
  225. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/constitution-sync/preset.yml +0 -0
  226. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/lean/README.md +0 -0
  227. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/lean/commands/speckit.constitution.md +0 -0
  228. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/lean/commands/speckit.implement.md +0 -0
  229. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/lean/commands/speckit.plan.md +0 -0
  230. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/lean/commands/speckit.specify.md +0 -0
  231. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/lean/commands/speckit.tasks.md +0 -0
  232. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/lean/preset.yml +0 -0
  233. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/scaffold/README.md +0 -0
  234. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/scaffold/commands/speckit.myext.myextcmd.md +0 -0
  235. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/scaffold/commands/speckit.specify.md +0 -0
  236. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/scaffold/preset.yml +0 -0
  237. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/scaffold/templates/myext-template.md +0 -0
  238. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/scaffold/templates/spec-template.md +0 -0
  239. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/self-test/commands/speckit.specify.md +0 -0
  240. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/self-test/commands/speckit.wrap-test.md +0 -0
  241. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/self-test/preset.yml +0 -0
  242. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/self-test/templates/checklist-template.md +0 -0
  243. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/self-test/templates/constitution-template.md +0 -0
  244. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/self-test/templates/plan-template.md +0 -0
  245. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/self-test/templates/spec-template.md +0 -0
  246. {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/self-test/templates/tasks-template.md +0 -0
  247. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/bash/check-prerequisites.sh +0 -0
  248. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/bash/create-new-feature.sh +0 -0
  249. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/bash/resolve-template.sh +0 -0
  250. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/bash/setup-plan.sh +0 -0
  251. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/bash/setup-tasks.sh +0 -0
  252. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/powershell/check-prerequisites.ps1 +0 -0
  253. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/powershell/common.ps1 +0 -0
  254. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/powershell/resolve-template.ps1 +0 -0
  255. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/powershell/setup-plan.ps1 +0 -0
  256. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/powershell/setup-tasks.ps1 +0 -0
  257. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/python/check_prerequisites.py +0 -0
  258. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/python/common.py +0 -0
  259. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/python/create_new_feature.py +0 -0
  260. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/python/resolve_template.py +0 -0
  261. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/python/setup_plan.py +0 -0
  262. {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/python/setup_tasks.py +0 -0
  263. {specify_cli-1.0.3 → specify_cli-1.0.4}/spec-driven.md +0 -0
  264. {specify_cli-1.0.3 → specify_cli-1.0.4}/spec-kit.code-workspace +0 -0
  265. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/__init__.py +0 -0
  266. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_agent_config.py +0 -0
  267. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_assets.py +0 -0
  268. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_console.py +0 -0
  269. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_download_security.py +0 -0
  270. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_github_http.py +0 -0
  271. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_init_options.py +0 -0
  272. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_project.py +0 -0
  273. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_toml_string.py +0 -0
  274. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_utils.py +0 -0
  275. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_version.py +0 -0
  276. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/agents.py +0 -0
  277. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/authentication/__init__.py +0 -0
  278. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/authentication/azure_devops.py +0 -0
  279. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/authentication/base.py +0 -0
  280. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/authentication/github.py +0 -0
  281. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/authentication/http.py +0 -0
  282. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/__init__.py +0 -0
  283. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/commands_impl/__init__.py +0 -0
  284. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/commands_impl/catalog_config.py +0 -0
  285. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/lib/__init__.py +0 -0
  286. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/lib/project.py +0 -0
  287. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/lib/versioning.py +0 -0
  288. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/lib/yamlio.py +0 -0
  289. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/models/__init__.py +0 -0
  290. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/models/manifest.py +0 -0
  291. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/__init__.py +0 -0
  292. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/adapters.py +0 -0
  293. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/catalog_stack.py +0 -0
  294. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/conflict.py +0 -0
  295. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/installer.py +0 -0
  296. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/packager.py +0 -0
  297. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/primitives.py +0 -0
  298. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/references.py +0 -0
  299. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/resolver.py +0 -0
  300. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/validator.py +0 -0
  301. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/catalogs.py +0 -0
  302. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/commands/__init__.py +0 -0
  303. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/commands/bundle/__init__.py +0 -0
  304. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/commands/event.py +0 -0
  305. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/events.py +0 -0
  306. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/extensions/__init__.py +0 -0
  307. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integration_runtime.py +0 -0
  308. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integration_scaffold.py +0 -0
  309. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integration_state.py +0 -0
  310. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integration_status.py +0 -0
  311. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/_commands.py +0 -0
  312. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/_helpers.py +0 -0
  313. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/_install_commands.py +0 -0
  314. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/_migrate_commands.py +0 -0
  315. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/_query_commands.py +0 -0
  316. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/_scaffold_commands.py +0 -0
  317. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/agy/__init__.py +0 -0
  318. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/alquimia/__init__.py +0 -0
  319. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/amp/__init__.py +0 -0
  320. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/auggie/__init__.py +0 -0
  321. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/base.py +0 -0
  322. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/bob/__init__.py +0 -0
  323. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/catalog.py +0 -0
  324. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/claude/__init__.py +0 -0
  325. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/cline/__init__.py +0 -0
  326. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/codebuddy/__init__.py +0 -0
  327. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/codex/__init__.py +0 -0
  328. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/command_code/__init__.py +0 -0
  329. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/copilot/__init__.py +0 -0
  330. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/cursor_agent/__init__.py +0 -0
  331. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/devin/__init__.py +0 -0
  332. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/docker_agent/__init__.py +0 -0
  333. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/droid/__init__.py +0 -0
  334. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/firebender/__init__.py +0 -0
  335. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/forge/__init__.py +0 -0
  336. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/gemini/__init__.py +0 -0
  337. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/generic/__init__.py +0 -0
  338. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/goose/__init__.py +0 -0
  339. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/grok/__init__.py +0 -0
  340. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/hermes/__init__.py +0 -0
  341. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/junie/__init__.py +0 -0
  342. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/kilocode/__init__.py +0 -0
  343. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/kimi/__init__.py +0 -0
  344. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/kiro_cli/__init__.py +0 -0
  345. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/lingma/__init__.py +0 -0
  346. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/manifest.py +0 -0
  347. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/omp/__init__.py +0 -0
  348. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/opencode/__init__.py +0 -0
  349. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/pi/__init__.py +0 -0
  350. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/qodercli/__init__.py +0 -0
  351. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/qwen/__init__.py +0 -0
  352. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/shai/__init__.py +0 -0
  353. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/tabnine/__init__.py +0 -0
  354. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/trae/__init__.py +0 -0
  355. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/vibe/__init__.py +0 -0
  356. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/zcode/__init__.py +0 -0
  357. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/zed/__init__.py +0 -0
  358. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/shared_infra.py +0 -0
  359. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/__init__.py +0 -0
  360. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/base.py +0 -0
  361. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/engine.py +0 -0
  362. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/overlays/__init__.py +0 -0
  363. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/overlays/composer.py +0 -0
  364. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/overlays/layer_sources.py +0 -0
  365. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/overlays/merge.py +0 -0
  366. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/__init__.py +0 -0
  367. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/command/__init__.py +0 -0
  368. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/do_while/__init__.py +0 -0
  369. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/fan_in/__init__.py +0 -0
  370. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/fan_out/__init__.py +0 -0
  371. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/gate/__init__.py +0 -0
  372. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/if_then/__init__.py +0 -0
  373. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/init/__init__.py +0 -0
  374. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/prompt/__init__.py +0 -0
  375. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/shell/__init__.py +0 -0
  376. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/switch/__init__.py +0 -0
  377. {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/while_loop/__init__.py +0 -0
  378. {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/checklist-template.md +0 -0
  379. {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/analyze.md +0 -0
  380. {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/checklist.md +0 -0
  381. {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/clarify.md +0 -0
  382. {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/constitution.md +0 -0
  383. {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/converge.md +0 -0
  384. {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/implement.md +0 -0
  385. {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/plan.md +0 -0
  386. {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/specify.md +0 -0
  387. {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/tasks.md +0 -0
  388. {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/taskstoissues.md +0 -0
  389. {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/constitution-template.md +0 -0
  390. {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/plan-template.md +0 -0
  391. {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/spec-template.md +0 -0
  392. {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/tasks-template.md +0 -0
  393. {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/vscode-settings.json +0 -0
  394. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/__init__.py +0 -0
  395. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/auth_helpers.py +0 -0
  396. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/bundler_helpers.py +0 -0
  397. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/conftest.py +0 -0
  398. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/contract/test_bundle_cli.py +0 -0
  399. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/contract/test_manifest_schema.py +0 -0
  400. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/contract/test_wheel_bundled_presets.py +0 -0
  401. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/contract/test_wheel_core_pack_scripts.py +0 -0
  402. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/__init__.py +0 -0
  403. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/assess/__init__.py +0 -0
  404. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/assess/test_assess_extension.py +0 -0
  405. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/bug/__init__.py +0 -0
  406. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/bug/test_bug_extension.py +0 -0
  407. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/git/__init__.py +0 -0
  408. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/git/test_git_extension.py +0 -0
  409. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/git/test_git_extension_python_parity.py +0 -0
  410. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/test_agent_context_cli_free.py +0 -0
  411. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/test_extension_agent_context.py +0 -0
  412. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/test_update_agent_context_feature_json.py +0 -0
  413. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/test_update_agent_context_python_parity.py +0 -0
  414. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/hooks/TESTING.md +0 -0
  415. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/hooks/plan.md +0 -0
  416. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/hooks/spec.md +0 -0
  417. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/hooks/tasks.md +0 -0
  418. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/http_helpers.py +0 -0
  419. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integration/test_bundler_catalog_stack.py +0 -0
  420. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integration/test_bundler_init_install.py +0 -0
  421. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integration/test_bundler_install_flow.py +0 -0
  422. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integration/test_bundler_local_install.py +0 -0
  423. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integration/test_bundler_offline.py +0 -0
  424. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integration/test_bundler_security_paths.py +0 -0
  425. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/__init__.py +0 -0
  426. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/conftest.py +0 -0
  427. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_base.py +0 -0
  428. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_cli.py +0 -0
  429. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_events.py +0 -0
  430. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_extra_args.py +0 -0
  431. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_home_isolation.py +0 -0
  432. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_agy.py +0 -0
  433. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_alquimia.py +0 -0
  434. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_amp.py +0 -0
  435. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_auggie.py +0 -0
  436. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_base_markdown.py +0 -0
  437. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_base_skills.py +0 -0
  438. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_base_toml.py +0 -0
  439. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_base_yaml.py +0 -0
  440. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_bob.py +0 -0
  441. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_catalog.py +0 -0
  442. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_claude.py +0 -0
  443. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_cline.py +0 -0
  444. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_codebuddy.py +0 -0
  445. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_codex.py +0 -0
  446. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_command_code.py +0 -0
  447. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_copilot.py +0 -0
  448. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_cursor_agent.py +0 -0
  449. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_devin.py +0 -0
  450. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_docker_agent.py +0 -0
  451. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_droid.py +0 -0
  452. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_firebender.py +0 -0
  453. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_forge.py +0 -0
  454. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_gemini.py +0 -0
  455. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_generic.py +0 -0
  456. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_goose.py +0 -0
  457. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_grok.py +0 -0
  458. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_hermes.py +0 -0
  459. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_junie.py +0 -0
  460. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_kilocode.py +0 -0
  461. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_kimi.py +0 -0
  462. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_kiro_cli.py +0 -0
  463. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_lingma.py +0 -0
  464. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_omp.py +0 -0
  465. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_opencode.py +0 -0
  466. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_pi.py +0 -0
  467. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_qodercli.py +0 -0
  468. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_qwen.py +0 -0
  469. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_scaffold.py +0 -0
  470. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_shai.py +0 -0
  471. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_state.py +0 -0
  472. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_subcommand.py +0 -0
  473. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_tabnine.py +0 -0
  474. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_trae.py +0 -0
  475. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_vibe.py +0 -0
  476. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_zcode.py +0 -0
  477. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_zed.py +0 -0
  478. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_manifest.py +0 -0
  479. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_skill_frontmatter_quoting.py +0 -0
  480. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/self_upgrade_helpers.py +0 -0
  481. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_branch_numbering.py +0 -0
  482. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_check_prerequisites_paths_only.py +0 -0
  483. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_check_prerequisites_python_parity.py +0 -0
  484. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_check_tool.py +0 -0
  485. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_cli_version.py +0 -0
  486. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_command_template_py_scripts.py +0 -0
  487. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_commands_package.py +0 -0
  488. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_console_imports.py +0 -0
  489. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_download_security.py +0 -0
  490. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_event_command.py +0 -0
  491. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_extension_add_path_traversal.py +0 -0
  492. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_extension_registration.py +0 -0
  493. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_extension_skills.py +0 -0
  494. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_extension_update_hardening.py +0 -0
  495. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_github_http.py +0 -0
  496. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_github_workflows.py +0 -0
  497. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_init_dir.py +0 -0
  498. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_init_dir_cli.py +0 -0
  499. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_init_output_markup.py +0 -0
  500. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_live_transient_windows.py +0 -0
  501. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_merge.py +0 -0
  502. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_post_process.py +0 -0
  503. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_ps1_encoding.py +0 -0
  504. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_registrar_path_traversal.py +0 -0
  505. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_security_workflow.py +0 -0
  506. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_self_upgrade_detection.py +0 -0
  507. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_self_upgrade_execution.py +0 -0
  508. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_self_upgrade_guidance.py +0 -0
  509. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_self_upgrade_verification.py +0 -0
  510. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_setup_plan_feature_json.py +0 -0
  511. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_setup_plan_no_overwrite.py +0 -0
  512. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_setup_plan_python_parity.py +0 -0
  513. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_setup_tasks.py +0 -0
  514. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_setup_tasks_python_parity.py +0 -0
  515. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_shared_infra_gitignore.py +0 -0
  516. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_shared_infra_integrity.py +0 -0
  517. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_skill_placeholder_py.py +0 -0
  518. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_specify_template_numbering.py +0 -0
  519. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_timestamp_branches.py +0 -0
  520. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_upgrade.py +0 -0
  521. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_utils.py +0 -0
  522. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_utils_assets_imports.py +0 -0
  523. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_version_imports.py +0 -0
  524. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_workflow_run_without_project.py +0 -0
  525. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundle_download_url.py +0 -0
  526. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_adapters.py +0 -0
  527. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_catalog_config.py +0 -0
  528. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_conflict.py +0 -0
  529. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_packager.py +0 -0
  530. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_primitives.py +0 -0
  531. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_references.py +0 -0
  532. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_resolver.py +0 -0
  533. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_validator.py +0 -0
  534. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_versioning.py +0 -0
  535. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_yamlio.py +0 -0
  536. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_condition_expression_block.py +0 -0
  537. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/workflows/conftest.py +0 -0
  538. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/workflows/test_overlay_composer.py +0 -0
  539. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/workflows/test_overlay_layer_sources.py +0 -0
  540. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/workflows/test_overlay_merge.py +0 -0
  541. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/workflows/test_overlay_security.py +0 -0
  542. {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/workflows/test_resolver_integration.py +0 -0
  543. {specify_cli-1.0.3 → specify_cli-1.0.4}/workflows/ARCHITECTURE.md +0 -0
  544. {specify_cli-1.0.3 → specify_cli-1.0.4}/workflows/PUBLISHING.md +0 -0
  545. {specify_cli-1.0.3 → specify_cli-1.0.4}/workflows/README.md +0 -0
  546. {specify_cli-1.0.3 → specify_cli-1.0.4}/workflows/catalog.community.json +0 -0
  547. {specify_cli-1.0.3 → specify_cli-1.0.4}/workflows/catalog.json +0 -0
  548. {specify_cli-1.0.3 → specify_cli-1.0.4}/workflows/speckit/workflow.yml +0 -0
  549. {specify_cli-1.0.3 → specify_cli-1.0.4}/workflows/step-catalog.community.json +0 -0
  550. {specify_cli-1.0.3 → specify_cli-1.0.4}/workflows/step-catalog.json +0 -0
@@ -8,7 +8,7 @@ body:
8
8
  value: |
9
9
  Thanks for requesting a new agent! Before submitting, please check if the agent is already supported.
10
10
 
11
- **Currently supported agents**: Alquimia AI, Amp, Antigravity, Auggie CLI, Claude Code, Cline, CodeBuddy, Codex CLI, Command Code, Cursor, Devin for Terminal, Docker Agent, Factory Droid, Firebender, Forge, Gemini CLI, GitHub Copilot, Goose, Grok Build, Hermes Agent, IBM Bob, Junie, Kilo Code, Kimi Code, Kiro CLI, Lingma, Mistral Vibe, Oh My Pi, opencode, Pi Coding Agent, Qoder CLI, Qwen Code, RovoDev ACLI, SHAI, Tabnine CLI, Trae, ZCode, Zed
11
+ **Currently supported agents**: Alquimia AI, Amp, Antigravity, Auggie CLI, Claude Code, Cline, CodeBuddy, Codex CLI, Command Code, Cursor, Devin for Terminal, Docker Agent, Factory Droid, DeepSeek Harness, Firebender, Forge, Gemini CLI, GitHub Copilot, Goose, Grok Build, Hermes Agent, IBM Bob, Junie, Kilo Code, Kimi Code, Kiro CLI, Lingma, Mistral Vibe, Oh My Pi, opencode, Pi Coding Agent, Qoder CLI, Qwen Code, RovoDev ACLI, SHAI, Tabnine CLI, Trae, ZCode, Zed
12
12
 
13
13
  - type: input
14
14
  id: agent-name
@@ -75,6 +75,7 @@ body:
75
75
  - Devin for Terminal
76
76
  - Docker Agent
77
77
  - Factory Droid
78
+ - DeepSeek Harness
78
79
  - Firebender
79
80
  - Forge
80
81
  - Gemini CLI
@@ -69,6 +69,7 @@ body:
69
69
  - Devin for Terminal
70
70
  - Docker Agent
71
71
  - Factory Droid
72
+ - DeepSeek Harness
72
73
  - Firebender
73
74
  - Forge
74
75
  - Gemini CLI
@@ -506,7 +506,7 @@ Disclosure is **continuous**, not a one-time event. A single AI-disclosure parag
506
506
  ### Opening pull requests
507
507
 
508
508
  - Before opening a pull request, check whether the account that will file it already has three open pull requests in this repository.
509
- - If so, alert the user that additional submissions may receive lower review priority and ask for explicit permission to proceed. Do not assume consent.
509
+ - If so, alert the user that additional submissions may receive lower review priority and ask for explicit permission to proceed. Do not assume consent. If the user is unavailable to provide that permission, including during autonomous or non-interactive operation, do not open the pull request. Preserve the work on a branch and report that confirmation is required.
510
510
 
511
511
  ### Commits
512
512
 
@@ -2,6 +2,31 @@
2
2
 
3
3
  <!-- insert new changelog below this comment -->
4
4
 
5
+ ## [1.0.4] - 2026-09-02
6
+
7
+ ### Changed
8
+
9
+ - fix(scripts): stop wrap composition looping on a token in core content (#4396)
10
+ - [extension] Update Charter extension to v0.6.1 (#4409)
11
+ - fix(workflows): keep non-ASCII text readable in written overlay files (#4148)
12
+ - fix(workflows): report overlay operation keys in declaration order (#4146)
13
+ - fix: skip corrupted state.json in list_runs() instead of aborting (#3904)
14
+ - fix(rovodev): guard non-string prompt names when merging prompts.yml (#4145)
15
+ - fix: narrow bare except Exception in preset command reconciliation (#3842)
16
+ - fix(workflows): refuse a filter mixed with a comparison operator instead of silently mis-binding it (#3894)
17
+ - fix: escape Rich markup in workflow error output (#3837)
18
+ - fix: add JSON error handling to auth config loader (#3836)
19
+ - fix: use missing_ok=True in extension ZIP cleanup (#3870)
20
+ - feat(presets): let a preset declare a required extension (#4250)
21
+ - fix(bundler): reject unsupported catalog payload versions (#4090)
22
+ - fix(extensions): install bundled extension updates from the local package (#4351)
23
+ - docs: clarify autonomous PR handling (#4392)
24
+ - fix(workflows): reject malformed step config on add (#4087)
25
+ - fix(powershell): stop create-new-feature crashing on a non-Latin description (#4138)
26
+ - fix(bundler): treat an explicit-null records field as missing, not "None" (#4136)
27
+ - Add DeepSeek Harness (DSH) integration (#4336)
28
+ - chore: release 1.0.3, begin 1.0.4.dev0 development (#4391)
29
+
5
30
  ## [1.0.3] - 2026-09-01
6
31
 
7
32
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: specify-cli
3
- Version: 1.0.3
3
+ Version: 1.0.4
4
4
  Summary: Specify CLI, part of GitHub Spec Kit. A tool to bootstrap your projects for Spec-Driven Development (SDD).
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.11
@@ -52,7 +52,7 @@ The following community-contributed extensions are available in [`catalog.commun
52
52
  | Bugfix Workflow | Structured bugfix workflow — capture bugs, trace to spec artifacts, and patch specs surgically | `process` | Read+Write | [spec-kit-bugfix](https://github.com/Quratulain-bilal/spec-kit-bugfix) |
53
53
  | Canon | Adds canon-driven (baseline-driven) workflows: spec-first, code-first, spec-drift. Requires Canon Core preset installation. | `process` | Read+Write | [spec-kit-canon](https://github.com/maximiliamus/spec-kit-canon/tree/master/extension) |
54
54
  | Catalog CI | Automated validation for spec-kit community catalog entries — structure, URLs, diffs, and linting | `process` | Read-only | [spec-kit-catalog-ci](https://github.com/Quratulain-bilal/spec-kit-catalog-ci) |
55
- | Charter | Compose modular project constitutions from shared fragment registries. Centralize governance rules, select per-project fragments, track upstream changes, and keep multi-project setups consistent. | `process` | Read+Write | [spec-kit-charter](https://github.com/Fyloss/spec-kit-charter) |
55
+ | Charter | Compose project constitutions from shared fragment registries | `process` | Read+Write | [spec-kit-charter](https://github.com/Fyloss/spec-kit-charter) |
56
56
  | CI Guard | Spec compliance gates for CI/CD — verify specs exist, check drift, and block merges on gaps | `process` | Read-only | [spec-kit-ci-guard](https://github.com/Quratulain-bilal/spec-kit-ci-guard) |
57
57
  | Checkpoint Extension | Commit the changes made during the middle of the implementation, so you don't end up with just one very large commit at the end | `code` | Read+Write | [spec-kit-checkpoint](https://github.com/aaronrsun/spec-kit-checkpoint) |
58
58
  | Cleanup Extension | Post-implementation quality gate that reviews changes, fixes small issues (scout rule), creates tasks for medium issues, and generates analysis for large issues | `code` | Read+Write | [spec-kit-cleanup](https://github.com/dsrednicki/spec-kit-cleanup) |
@@ -75,6 +75,8 @@ specify extension update [<name>]
75
75
 
76
76
  Updates a specific extension, or all installed extensions if no name is given.
77
77
 
78
+ Bundled extensions (such as `agent-context` and `git`) have no download URL; their updates install from the copy shipped with the running spec-kit release. When the catalog advertises a newer version than your spec-kit release ships, the update is reported as requiring a spec-kit upgrade first.
79
+
78
80
  ## Enable / Disable an Extension
79
81
 
80
82
  ```bash
@@ -16,6 +16,7 @@ The Specify CLI supports a wide range of AI coding agents. When you run `specify
16
16
  | [Codex CLI](https://github.com/openai/codex) | `codex` | Skills-based integration; installs skills into `.agents/skills` and invokes them as `$speckit-<command>` |
17
17
  | [Command Code](https://commandcode.ai/docs) | `command-code` | Skills-based integration; installs skills into `.commandcode/skills/` and invokes them as `$speckit-<command>` |
18
18
  | [Cursor](https://cursor.sh/) | `cursor-agent` | |
19
+ | [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) | `dsh` | Skills-based integration; installs skills into `.dsh/skills` and invokes them as `/speckit-<command>` |
19
20
  | [Devin for Terminal](https://cli.devin.ai/docs) | `devin` | Skills-based integration; installs skills into `.devin/skills/` and invokes them as `/speckit-<command>` |
20
21
  | [Docker Agent](https://docs.docker.com/ai/docker-agent/) | `docker-agent` | Skills-based integration; installs skills into `.agents/skills/` (the same directory used by Codex and Zed). In the selected agent YAML, enable local skills with `skills: true` and provide filesystem read access. Detects either the standalone `docker-agent` binary or the Docker CLI plugin (`docker agent`). Configure workflow dispatch with `SPECKIT_INTEGRATION_DOCKER_AGENT_EXTRA_ARGS=./agent.yaml`; the Spec Kit prompt is appended after these arguments. Not multi-install safe by default because the skills directory is shared. |
21
22
  | [Factory Droid](https://docs.factory.ai/cli/getting-started/overview) | `droid` | Skills-based integration; installs skills into `.factory/skills/` and invokes them as `/speckit-<command>` |
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema_version": "1.0",
3
- "updated_at": "2026-09-01T00:00:00Z",
3
+ "updated_at": "2026-09-02T00:00:00Z",
4
4
  "catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.community.json",
5
5
  "extensions": {
6
6
  "adrkit": {
@@ -1039,13 +1039,13 @@
1039
1039
  "charter": {
1040
1040
  "name": "Charter",
1041
1041
  "id": "charter",
1042
- "description": "Compose modular project constitutions from shared fragment registries. Centralize governance rules, select per-project fragments, track upstream changes, and keep multi-project setups consistent.",
1042
+ "description": "Compose project constitutions from shared fragment registries",
1043
1043
  "author": "Fyloss",
1044
- "version": "0.5.1",
1045
- "download_url": "https://github.com/Fyloss/spec-kit-charter/archive/refs/tags/v0.5.1.zip",
1044
+ "version": "0.6.1",
1045
+ "download_url": "https://github.com/Fyloss/spec-kit-charter/archive/refs/tags/v0.6.1.zip",
1046
1046
  "repository": "https://github.com/Fyloss/spec-kit-charter",
1047
1047
  "homepage": "https://github.com/Fyloss/spec-kit-charter",
1048
- "documentation": "https://github.com/Fyloss/spec-kit-charter/tree/master/docs",
1048
+ "documentation": "https://github.com/Fyloss/spec-kit-charter/blob/master/README.md",
1049
1049
  "changelog": "https://github.com/Fyloss/spec-kit-charter/blob/master/CHANGELOG.md",
1050
1050
  "license": "MIT",
1051
1051
  "category": "process",
@@ -1066,15 +1066,15 @@
1066
1066
  "tags": [
1067
1067
  "constitution",
1068
1068
  "governance",
1069
- "modular",
1070
- "fragments",
1071
- "registry"
1069
+ "multi-repo",
1070
+ "composition",
1071
+ "fragments"
1072
1072
  ],
1073
1073
  "verified": false,
1074
1074
  "downloads": 0,
1075
1075
  "stars": 0,
1076
1076
  "created_at": "2026-07-06T00:00:00Z",
1077
- "updated_at": "2026-08-04T00:00:00Z"
1077
+ "updated_at": "2026-09-02T00:00:00Z"
1078
1078
  },
1079
1079
  "ci-guard": {
1080
1080
  "name": "CI Guard",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema_version": "1.0",
3
- "updated_at": "2026-08-26T00:00:00Z",
3
+ "updated_at": "2026-08-31T00:00:00Z",
4
4
  "catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/integrations/catalog.json",
5
5
  "integrations": {
6
6
  "alquimia": {
@@ -66,6 +66,15 @@
66
66
  "repository": "https://github.com/github/spec-kit",
67
67
  "tags": ["cli", "skills", "factory"]
68
68
  },
69
+ "dsh": {
70
+ "id": "dsh",
71
+ "name": "DeepSeek Harness",
72
+ "version": "1.0.0",
73
+ "description": "DeepSeek Harness (DSH) CLI skills-based integration",
74
+ "author": "spec-kit-core",
75
+ "repository": "https://github.com/github/spec-kit",
76
+ "tags": ["cli", "skills"]
77
+ },
69
78
  "amp": {
70
79
  "id": "amp",
71
80
  "name": "Amp",
@@ -68,6 +68,8 @@ preset:
68
68
 
69
69
  requires:
70
70
  speckit_version: ">=0.1.0" # Required spec-kit version
71
+ extensions: # Optional: extensions this preset needs
72
+ - "companion-extension"
71
73
 
72
74
  provides:
73
75
  templates:
@@ -93,6 +95,41 @@ tags: # 2-5 relevant tags
93
95
  - ✅ Command names use dot notation (e.g. `speckit.specify`)
94
96
  - ✅ Tags are lowercase and descriptive
95
97
 
98
+ #### Declaring extension dependencies
99
+
100
+ If your preset overrides commands that call into an extension, declare it in
101
+ `requires.extensions`. Without the extension the preset still installs and the
102
+ overrides fall through to the core workflow, so nothing errors — the feature
103
+ just silently does less than the user expects. Declaring the dependency makes
104
+ `specify preset add` say so, and spell out how to resolve it.
105
+
106
+ Use a bare id, or a mapping when you need a version constraint or an optional
107
+ dependency:
108
+
109
+ ```yaml
110
+ requires:
111
+ speckit_version: ">=0.9.0"
112
+ extensions:
113
+ - "companion-extension" # required, any version
114
+ - id: "other-extension"
115
+ version: ">=1.2.0,<2" # optional PEP 440 specifier
116
+ required: false # optional, defaults to true
117
+ ```
118
+
119
+ `version` accepts any PEP 440 specifier, not just a lower bound — upper bounds
120
+ (`<2`), exact pins (`==1.2.0`), and exclusions (`!=1.3.0`) all work.
121
+
122
+ Notes:
123
+
124
+ - The field is optional. A preset that declares nothing behaves exactly as before.
125
+ - A dependency that is missing, stale, disabled, or version-unsatisfied produces a **warning, not a failure** — the install still succeeds.
126
+ - A disabled extension counts as unmet, and so does one whose registry entry survives after its files were removed. Resolution skips both, so the preset is just as inert as if the extension were absent.
127
+ - The warning names an exact command for the missing, stale, and disabled cases. For a version mismatch it states the constraint to satisfy rather than naming a command, because `specify extension update` only moves forward to the catalog release and cannot satisfy an upper bound, a pin, or a downgrade.
128
+ - A recorded version that cannot be parsed is treated as uncomparable rather than as a mismatch, so an extension whose registry version reads `unknown` is not reported as failing a constraint it was never evaluated against.
129
+ - An extension present on disk but absent from the registry counts as satisfied. Resolution admits unregistered directories, so the preset works and warning about it would be a false alarm — though with no recorded version, a `version` constraint cannot be checked against it.
130
+ - `required: false` documents an enhancing-but-optional extension and is never warned about.
131
+ - Declare it in `preset.yml`, not only in your catalog entry. The catalog is not consulted for `--dev` and `--from <url>` installs, so the manifest is the only copy present on every install path.
132
+
96
133
  ### 3. Test Locally
97
134
 
98
135
  ```bash
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "specify-cli"
3
- version = "1.0.3"
3
+ version = "1.0.4"
4
4
  description = "Specify CLI, part of GitHub Spec Kit. A tool to bootstrap your projects for Spec-Driven Development (SDD)."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -902,12 +902,20 @@ except Exception as exc:
902
902
  *'{CORE_TEMPLATE}'*) ;;
903
903
  *) echo "Error: wrap strategy missing {CORE_TEMPLATE} placeholder" >&2; return 2 ;;
904
904
  esac
905
- while [[ "$layer_content" == *'{CORE_TEMPLATE}'* ]]; do
906
- local before="${layer_content%%\{CORE_TEMPLATE\}*}"
907
- local after="${layer_content#*\{CORE_TEMPLATE\}}"
908
- layer_content="${before}${content}${after}"
905
+ # Consume the wrapper left to right instead of rewriting it in
906
+ # place. Rewriting re-scanned the string just modified, so base
907
+ # content holding a literal {CORE_TEMPLATE} reintroduced the
908
+ # token every pass and the loop never terminated. Advancing over
909
+ # ``rest`` bounds the work by the tokens in the original wrapper
910
+ # and leaves inserted content untouched, matching the single-pass
911
+ # semantics of .Replace()/.replace() in the PowerShell and Python
912
+ # ports.
913
+ local wrapped="" rest="$layer_content"
914
+ while [[ "$rest" == *'{CORE_TEMPLATE}'* ]]; do
915
+ wrapped="${wrapped}${rest%%\{CORE_TEMPLATE\}*}${content}"
916
+ rest="${rest#*\{CORE_TEMPLATE\}}"
909
917
  done
910
- content="$layer_content"
918
+ content="${wrapped}${rest}"
911
919
  ;;
912
920
  *) echo "Error: unknown strategy '$strat'" >&2; return 2 ;;
913
921
  esac
@@ -162,7 +162,14 @@ function Get-BranchName {
162
162
  } else {
163
163
  # Fallback to original logic if no meaningful words found
164
164
  $result = ConvertTo-CleanBranchName -Name $Description
165
- $fallbackWords = ($result -split '-') | Where-Object { $_ } | Select-Object -First 3
165
+ # @() keeps this an array. ConvertTo-CleanBranchName blanks every
166
+ # non-[a-z0-9] character, so a description written in a non-Latin script
167
+ # (or made only of punctuation) leaves nothing for the pipeline to
168
+ # emit -- it yields $null, and [string]::Join on $null throws
169
+ # ArgumentNullException. With $ErrorActionPreference = 'Stop' that is
170
+ # terminating, so the script died with a .NET stack trace and exit 1
171
+ # where the bash and Python twins both return an empty suffix.
172
+ $fallbackWords = @(($result -split '-') | Where-Object { $_ } | Select-Object -First 3)
166
173
  return [string]::Join('-', $fallbackWords)
167
174
  }
168
175
  }
@@ -13,7 +13,7 @@ DOLLAR_SKILLS_AGENTS: frozenset[str] = frozenset({"codex", "zcode", "command-cod
13
13
 
14
14
  # Agents that always render /speckit-<name>, regardless of ai_skills.
15
15
  ALWAYS_SLASH_AGENTS: frozenset[str] = frozenset(
16
- {"devin", "droid", "grok", "qodercli", "trae", "zed"}
16
+ {"devin", "droid", "dsh", "grok", "qodercli", "trae", "zed"}
17
17
  )
18
18
 
19
19
  # Agents that render /speckit-<name> only when ai_skills is enabled.
@@ -112,7 +112,10 @@ def load_auth_config(
112
112
  except OSError:
113
113
  pass # stat failed — skip permission check
114
114
 
115
- raw = json.loads(config_path.read_text(encoding="utf-8"))
115
+ try:
116
+ raw = json.loads(config_path.read_text(encoding="utf-8"))
117
+ except json.JSONDecodeError as exc:
118
+ raise ValueError(f"{config_path} contains invalid JSON: {exc}") from exc
116
119
 
117
120
  if not isinstance(raw, dict):
118
121
  raise ValueError(f"auth.json must be a JSON object, got {type(raw).__name__}")
@@ -20,6 +20,7 @@ CONFIG_FILENAME = "bundle-catalogs.yml"
20
20
  # reject an unsupported major version so a file written by a newer/incompatible
21
21
  # Spec Kit fails fast instead of being parsed under the wrong assumptions.
22
22
  CONFIG_SCHEMA_VERSION = "1.0"
23
+ CATALOG_SCHEMA_VERSION = "1.0"
23
24
 
24
25
 
25
26
  class InstallPolicy(str, Enum):
@@ -220,6 +221,16 @@ def load_catalog_payload(data: Any) -> dict[str, CatalogEntry]:
220
221
  """Parse a catalog JSON payload into ``{bundle_id: CatalogEntry}``."""
221
222
  if not isinstance(data, dict):
222
223
  raise BundlerError("Catalog payload must be a JSON object.")
224
+ schema_version = data.get("schema_version")
225
+ if schema_version is not None and (
226
+ str(schema_version).strip().split(".")[0]
227
+ != CATALOG_SCHEMA_VERSION.split(".")[0]
228
+ ):
229
+ raise BundlerError(
230
+ f"Unsupported catalog schema version "
231
+ f"'{str(schema_version).strip()}'; this Spec Kit understands "
232
+ f"version {CATALOG_SCHEMA_VERSION}."
233
+ )
223
234
  bundles_raw = data.get("bundles")
224
235
  if not isinstance(bundles_raw, dict):
225
236
  raise BundlerError("Catalog payload is missing a 'bundles' object.")
@@ -13,7 +13,7 @@ from typing import Any
13
13
 
14
14
  from .. import BundlerError
15
15
  from ..lib.yamlio import dump_json, ensure_within, load_json
16
- from .manifest import COMPONENT_KINDS, ComponentRef
16
+ from .manifest import COMPONENT_KINDS, ComponentRef, _text
17
17
 
18
18
  RECORDS_FILENAME = "bundle-records.json"
19
19
  RECORDS_SCHEMA_VERSION = "1.0"
@@ -65,8 +65,14 @@ class InstalledBundleRecord:
65
65
  raise BundlerError(
66
66
  "Corrupt record: 'contributed_components' must be a list."
67
67
  )
68
- bundle_id = str(data.get("bundle_id", "")).strip()
69
- version = str(data.get("version", "")).strip()
68
+ # ``.get(key, "")`` defaults only a *missing* key. A key that is
69
+ # present but null -- how a hand-edited or corrupt record spells an
70
+ # empty field -- yields ``None``, and ``str(None)`` is the non-empty
71
+ # literal ``"None"``, which sails past the required-field checks
72
+ # below. Reuse the manifest's ``_text`` so records and bundle.yml
73
+ # agree on what an explicit null means.
74
+ bundle_id = _text(data.get("bundle_id"))
75
+ version = _text(data.get("version"))
70
76
  if not bundle_id:
71
77
  raise BundlerError(
72
78
  "Corrupt records file: an installed-bundle record is missing "
@@ -80,7 +86,7 @@ class InstalledBundleRecord:
80
86
  return cls(
81
87
  bundle_id=bundle_id,
82
88
  version=version,
83
- installed_at=str(data.get("installed_at", "")).strip(),
89
+ installed_at=_text(data.get("installed_at")),
84
90
  contributed_components=tuple(
85
91
  _component_from_dict(c) for c in components_raw
86
92
  ),
@@ -201,8 +207,8 @@ def _component_to_dict(ref: ComponentRef) -> dict[str, Any]:
201
207
  def _component_from_dict(data: Any) -> ComponentRef:
202
208
  if not isinstance(data, dict):
203
209
  raise BundlerError("Each contributed component must be a mapping.")
204
- kind = str(data.get("kind", "")).strip()
205
- cid = str(data.get("id", "")).strip()
210
+ kind = _text(data.get("kind"))
211
+ cid = _text(data.get("id"))
206
212
  if kind not in COMPONENT_KINDS:
207
213
  raise BundlerError(
208
214
  f"Corrupt records file: component 'kind' must be one of "
@@ -1013,6 +1013,7 @@ def register(app: typer.Typer) -> None:
1013
1013
  devin_skill_mode = selected_ai == "devin"
1014
1014
  zed_skill_mode = selected_ai == "zed" and _is_skills_integration
1015
1015
  grok_skill_mode = selected_ai == "grok" and _is_skills_integration
1016
+ dsh_skill_mode = selected_ai == "dsh" and _is_skills_integration
1016
1017
  cline_skill_mode = selected_ai == "cline"
1017
1018
  forge_skill_mode = selected_ai == "forge"
1018
1019
  bob_skill_mode = selected_ai == "bob" and _is_skills_integration
@@ -1028,6 +1029,7 @@ def register(app: typer.Typer) -> None:
1028
1029
  or devin_skill_mode
1029
1030
  or zed_skill_mode
1030
1031
  or grok_skill_mode
1032
+ or dsh_skill_mode
1031
1033
  or bob_skill_mode
1032
1034
  )
1033
1035
 
@@ -1066,6 +1068,11 @@ def register(app: typer.Typer) -> None:
1066
1068
  f"{step_num}. Start Grok Build in this project directory; spec-kit skills were installed to [cyan].grok/skills[/cyan]"
1067
1069
  )
1068
1070
  step_num += 1
1071
+ if dsh_skill_mode:
1072
+ steps_lines.append(
1073
+ f"{step_num}. Start DSH ([cyan]dsh web[/cyan]) in this project directory; spec-kit skills were installed to [cyan].dsh/skills[/cyan]"
1074
+ )
1075
+ step_num += 1
1069
1076
  if bob_skill_mode:
1070
1077
  steps_lines.append(
1071
1078
  f"{step_num}. Start Bob in this project directory; spec-kit skills were installed to [cyan].bob/skills[/cyan]"
@@ -15,9 +15,12 @@ import shutil
15
15
  import stat
16
16
  import tempfile
17
17
  from pathlib import Path
18
- from typing import Optional
18
+ from typing import Optional, TYPE_CHECKING
19
19
  from uuid import uuid4
20
20
 
21
+ if TYPE_CHECKING:
22
+ from packaging.version import Version
23
+
21
24
  import typer
22
25
  import yaml
23
26
  from rich.markup import escape as _escape_markup
@@ -106,6 +109,58 @@ def _command_safe_id(raw_id: object, placeholder: str = "<extension-id>") -> str
106
109
  return placeholder
107
110
 
108
111
 
112
+ def _bundled_update_source(ext_id: str) -> tuple[Path, Version] | tuple[None, None]:
113
+ """Locate the local bundled copy of *ext_id* and its parsed version.
114
+
115
+ Bundled extensions have no download URL, so an update can only come
116
+ from the copy shipped with the running spec-kit release — which may
117
+ lag the version the catalog on main advertises. Returns
118
+ ``(path, Version)`` when a valid local copy exists, ``(None, None)``
119
+ otherwise.
120
+ """
121
+ from . import ExtensionManifest, ValidationError
122
+ from packaging import version as pkg_version
123
+
124
+ bundled_dir = _locate_bundled_extension(ext_id)
125
+ if bundled_dir is None:
126
+ return None, None
127
+ try:
128
+ manifest = ExtensionManifest(bundled_dir / "extension.yml")
129
+ return bundled_dir, pkg_version.Version(manifest.version)
130
+ except (ValidationError, pkg_version.InvalidVersion, OSError):
131
+ return None, None
132
+
133
+
134
+ def _archive_extension_directory(source_dir: Path) -> Path:
135
+ """Package an extension directory as a ZIP archive for the update flow.
136
+
137
+ The update pipeline validates and installs archives (bounded
138
+ extraction, manifest preflight, ID/version checks, backup/rollback),
139
+ so a locally bundled extension is fed through that identical hardened
140
+ path rather than growing a second install code path. The caller
141
+ deletes the archive after the update, the same as a downloaded one.
142
+ """
143
+ import zipfile
144
+
145
+ fd, tmp_name = tempfile.mkstemp(prefix="speckit-bundled-update-", suffix=".zip")
146
+ try:
147
+ with os.fdopen(fd, "wb") as archive_file:
148
+ with zipfile.ZipFile(archive_file, "w", zipfile.ZIP_DEFLATED) as zf:
149
+ for path in sorted(source_dir.rglob("*")):
150
+ # Never follow symlinks: is_file() follows the target
151
+ # and ZipFile.write() reads its bytes, which would turn
152
+ # an out-of-tree target into a regular archive member
153
+ # before the hardened extractor ever sees it.
154
+ if path.is_symlink():
155
+ continue
156
+ if path.is_file():
157
+ zf.write(path, path.relative_to(source_dir).as_posix())
158
+ except BaseException:
159
+ Path(tmp_name).unlink(missing_ok=True)
160
+ raise
161
+ return Path(tmp_name)
162
+
163
+
109
164
  def _refresh_events_and_warn(project_root: Path) -> None:
110
165
  """Refresh native event config and surface failures (R3).
111
166
 
@@ -1089,8 +1144,7 @@ def extension_add(
1089
1144
  force=force,
1090
1145
  )
1091
1146
  finally:
1092
- if archive_path.exists():
1093
- archive_path.unlink()
1147
+ archive_path.unlink(missing_ok=True)
1094
1148
 
1095
1149
  console.print("\n[green]✓[/green] Extension installed successfully!")
1096
1150
  console.print(f"\n[bold]{_escape_markup(str(manifest.name))}[/bold] (v{_escape_markup(str(manifest.version))})")
@@ -1622,6 +1676,7 @@ def extension_update(
1622
1676
  console.print("🔄 Checking for updates...\n")
1623
1677
 
1624
1678
  updates_available = []
1679
+ blocked_updates = []
1625
1680
 
1626
1681
  for ext_id in extensions_to_update:
1627
1682
  safe_ext_id = _escape_markup(str(ext_id))
@@ -1658,20 +1713,55 @@ def extension_update(
1658
1713
  continue
1659
1714
 
1660
1715
  if catalog_version > installed_version:
1716
+ download_url = ext_info.get("download_url")
1717
+ bundled_dir = None
1718
+ available_version = catalog_version
1719
+ if ext_info.get("bundled") and not download_url:
1720
+ # Bundled extensions cannot be downloaded; the update has
1721
+ # to come from the copy shipped with the running spec-kit
1722
+ # release, which may lag the catalog on main (#4345).
1723
+ bundled_dir, bundled_version = _bundled_update_source(ext_id)
1724
+ # Block whenever the local copy lags the catalog, not
1725
+ # just when it lags the installation: installing an
1726
+ # intermediate version would leave the project behind
1727
+ # the catalog while reporting success, contrary to the
1728
+ # documented "upgrade spec-kit first" behavior.
1729
+ if bundled_dir is None or bundled_version < catalog_version:
1730
+ local_desc = (
1731
+ f"only ships v{bundled_version}"
1732
+ if bundled_dir is not None
1733
+ else "does not ship a local copy"
1734
+ )
1735
+ console.print(
1736
+ f"⚠ {safe_ext_id}: v{catalog_version} is available, but this "
1737
+ f"spec-kit release {local_desc} — upgrade spec-kit, then rerun "
1738
+ f"'specify extension update'"
1739
+ )
1740
+ blocked_updates.append(ext_id)
1741
+ continue
1742
+ available_version = bundled_version
1661
1743
  updates_available.append(
1662
1744
  {
1663
1745
  "id": ext_id,
1664
1746
  "name": ext_info.get("name", ext_id), # Display name for status messages
1665
1747
  "installed": str(installed_version),
1666
- "available": str(catalog_version),
1667
- "download_url": ext_info.get("download_url"),
1748
+ "available": str(available_version),
1749
+ "download_url": download_url,
1750
+ "bundled_dir": bundled_dir,
1668
1751
  }
1669
1752
  )
1670
1753
  else:
1671
1754
  console.print(f"✓ {safe_ext_id}: Up to date (v{installed_version})")
1672
1755
 
1673
1756
  if not updates_available:
1674
- console.print("\n[green]All extensions are up to date![/green]")
1757
+ if blocked_updates:
1758
+ console.print(
1759
+ "\n[yellow]Update(s) exist but require a newer spec-kit "
1760
+ "release — upgrade spec-kit, then rerun "
1761
+ "'specify extension update'.[/yellow]"
1762
+ )
1763
+ else:
1764
+ console.print("\n[green]All extensions are up to date![/green]")
1675
1765
  raise typer.Exit(0)
1676
1766
 
1677
1767
  # Show available updates
@@ -1968,8 +2058,15 @@ def extension_update(
1968
2058
  if ext_hooks:
1969
2059
  backup_hooks[hook_name] = ext_hooks
1970
2060
 
1971
- # 5. Download new version
1972
- archive_path = catalog.download_extension(extension_id)
2061
+ # 5. Acquire the new version. Bundled extensions install from
2062
+ # the copy shipped with the running spec-kit release (they
2063
+ # have no download URL); everything else downloads. Both are
2064
+ # packaged as archives so the identical validation,
2065
+ # backup/rollback, and install pipeline below applies.
2066
+ if update.get("bundled_dir") is not None:
2067
+ archive_path = _archive_extension_directory(update["bundled_dir"])
2068
+ else:
2069
+ archive_path = catalog.download_extension(extension_id)
1973
2070
  try:
1974
2071
  # 6. Validate the archive and extension ID before modifying
1975
2072
  # the existing installation. The shared extractor applies
@@ -2312,11 +2409,10 @@ def extension_update(
2312
2409
  # Archive cleanup is housekeeping: never replace an install
2313
2410
  # error or roll back an already committed update because a
2314
2411
  # scanner temporarily locks the download on Windows.
2315
- if archive_path.exists():
2316
- try:
2317
- archive_path.unlink()
2318
- except OSError as error:
2319
- zip_cleanup_error = error
2412
+ try:
2413
+ archive_path.unlink(missing_ok=True)
2414
+ except OSError as error:
2415
+ zip_cleanup_error = error
2320
2416
 
2321
2417
  # 10. Clean up backup on success. The update has committed at
2322
2418
  # this point, so a locked backup file must not trigger rollback
@@ -62,6 +62,7 @@ def _register_builtins() -> None:
62
62
  from .devin import DevinIntegration
63
63
  from .docker_agent import DockerAgentIntegration
64
64
  from .droid import DroidIntegration
65
+ from .dsh import DshIntegration
65
66
  from .firebender import FirebenderIntegration
66
67
  from .forge import ForgeIntegration
67
68
  from .gemini import GeminiIntegration
@@ -103,6 +104,7 @@ def _register_builtins() -> None:
103
104
  _register(DevinIntegration())
104
105
  _register(DockerAgentIntegration())
105
106
  _register(DroidIntegration())
107
+ _register(DshIntegration())
106
108
  _register(FirebenderIntegration())
107
109
  _register(ForgeIntegration())
108
110
  _register(GeminiIntegration())