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.
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/ISSUE_TEMPLATE/agent_request.yml +1 -1
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/ISSUE_TEMPLATE/bug_report.yml +1 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/ISSUE_TEMPLATE/feature_request.yml +1 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/AGENTS.md +1 -1
- {specify_cli-1.0.3 → specify_cli-1.0.4}/CHANGELOG.md +25 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/PKG-INFO +1 -1
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/community/extensions.md +1 -1
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/extensions.md +2 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/integrations.md +1 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/catalog.community.json +9 -9
- {specify_cli-1.0.3 → specify_cli-1.0.4}/integrations/catalog.json +10 -1
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/PUBLISHING.md +37 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/pyproject.toml +1 -1
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/bash/common.sh +13 -5
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/powershell/create-new-feature.ps1 +8 -1
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_invocation_style.py +1 -1
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/authentication/config.py +4 -1
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/models/catalog.py +11 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/models/records.py +12 -6
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/commands/init.py +7 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/extensions/_commands.py +109 -13
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/__init__.py +2 -0
- specify_cli-1.0.4/src/specify_cli/integrations/dsh/__init__.py +64 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/rovodev/__init__.py +11 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/presets/__init__.py +280 -1
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/presets/_commands.py +112 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/_commands.py +3 -3
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/catalog.py +4 -2
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/expressions.py +34 -1
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/overlays/_commands.py +18 -2
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/overlays/schema.py +7 -1
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/contract/test_catalog_schema.py +17 -0
- specify_cli-1.0.4/tests/integrations/test_integration_dsh.py +314 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_rovodev.py +39 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_registry.py +1 -1
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/parity_helpers.py +11 -1
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_agent_config_consistency.py +1 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_authentication.py +1 -1
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_create_new_feature_python_parity.py +53 -0
- specify_cli-1.0.4/tests/test_extension_content_staleness.py +134 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_extensions.py +206 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_presets.py +591 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_resolve_template_python_parity.py +34 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_workflows.py +150 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_records.py +70 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/workflows/test_overlay_commands.py +109 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/workflows/test_overlay_schema.py +51 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.devcontainer/devcontainer.json +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.devcontainer/post-create.sh +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.editorconfig +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.gitattributes +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/CODEOWNERS +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/ISSUE_TEMPLATE/bundle_submission.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/ISSUE_TEMPLATE/extension_submission.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/ISSUE_TEMPLATE/preset_submission.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/aw/actions-lock.json +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/dependabot.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/scripts/check_security_requirements.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/security-audit-requirements.txt +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/skills/add-community-extension/SKILL.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/RELEASE-PROCESS.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/add-community-bundle.lock.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/add-community-bundle.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/add-community-extension.lock.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/add-community-extension.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/add-community-preset.lock.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/add-community-preset.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/bug-assess.lock.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/bug-assess.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/bug-fix.lock.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/bug-fix.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/bug-test.lock.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/bug-test.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/catalog-assign.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/codeql.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/docs.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/feature-assess.lock.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/feature-assess.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/lint.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/publish-pypi.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/release-trigger.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/release.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/security.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/stale.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.github/workflows/test.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.gitignore +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.markdownlint-cli2.jsonc +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.pre-commit-config.yaml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/.zenodo.json +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/CITATION.cff +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/CODE_OF_CONDUCT.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/CONTRIBUTING.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/DEVELOPMENT.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/LICENSE +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/README.zh-CN.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/SECURITY.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/SUPPORT.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/bundles/catalog.community.json +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/.gitignore +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/community/bundles.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/community/friends.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/community/overview.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/community/presets.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/community/walkthroughs.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/concepts/complex-features.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/concepts/sdd.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/concepts/spec-of-specs.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/concepts/spec-persistence.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/docfx.json +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/guides/evolving-specs.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/guides/existing-projects.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/guides/monorepo.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/history.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/images/spec-kit-logo.webp +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/index.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/install/air-gapped.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/install/one-time.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/install/pipx.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/install/pypi.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/install/uv.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/installation.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/local-development.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/quickstart.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/agentic-bugfix.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/agentic-sdd.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/authentication.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/bundles.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/core.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/overview.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/presets.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/reference/workflows.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/template/public/main.css +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/toc.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/docs/upgrade.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/examples/bundles/business-analyst/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/examples/bundles/business-analyst/bundle.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/examples/bundles/developer/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/examples/bundles/developer/bundle.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/examples/bundles/product-manager/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/examples/bundles/product-manager/bundle.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/examples/bundles/security-researcher/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/examples/bundles/security-researcher/bundle.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/EXTENSION-API-REFERENCE.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/EXTENSION-DEVELOPMENT-GUIDE.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/EXTENSION-PUBLISHING-GUIDE.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/EXTENSION-USER-GUIDE.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/RFC-EXTENSION-SYSTEM.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/agent-context/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/agent-context/agent-context-config.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/agent-context/agent-context-defaults.json +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/agent-context/commands/speckit.agent-context.update.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/agent-context/extension.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/agent-context/scripts/bash/update-agent-context.sh +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/agent-context/scripts/powershell/update-agent-context.ps1 +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/agent-context/scripts/python/update_agent_context.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/assess/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/assess/commands/speckit.assess.decide.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/assess/commands/speckit.assess.define.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/assess/commands/speckit.assess.intake.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/assess/commands/speckit.assess.research.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/assess/commands/speckit.assess.shape.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/assess/extension.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/bug/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/bug/commands/speckit.bug.assess.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/bug/commands/speckit.bug.fix.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/bug/commands/speckit.bug.test.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/bug/extension.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/catalog.json +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/commands/speckit.git.commit.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/commands/speckit.git.feature.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/commands/speckit.git.initialize.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/commands/speckit.git.remote.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/commands/speckit.git.validate.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/config-template.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/extension.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/git-config.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/bash/auto-commit.sh +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/bash/create-new-feature-branch.sh +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/bash/git-common.sh +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/bash/initialize-repo.sh +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/powershell/auto-commit.ps1 +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/powershell/create-new-feature-branch.ps1 +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/powershell/git-common.ps1 +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/powershell/initialize-repo.ps1 +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/python/auto_commit.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/python/create_new_feature_branch.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/python/git_common.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/git/scripts/python/initialize_repo.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/selftest/commands/selftest.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/selftest/extension.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/template/.gitignore +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/template/CHANGELOG.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/template/EXAMPLE-README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/template/LICENSE +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/template/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/template/commands/example.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/template/config-template.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/extensions/template/extension.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/integrations/CONTRIBUTING.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/integrations/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/integrations/catalog.community.json +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/media/bootstrap-claude-code.gif +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/media/logo_large.webp +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/media/logo_small.webp +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/media/spec-kit-video-header.jpg +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/media/specify_cli.gif +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/newsletters/2026-April.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/newsletters/2026-February.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/newsletters/2026-July.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/newsletters/2026-June.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/newsletters/2026-March.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/newsletters/2026-May.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/ARCHITECTURE.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/catalog.community.json +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/catalog.json +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/constitution-sync/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/constitution-sync/commands/speckit.constitution.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/constitution-sync/preset.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/lean/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/lean/commands/speckit.constitution.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/lean/commands/speckit.implement.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/lean/commands/speckit.plan.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/lean/commands/speckit.specify.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/lean/commands/speckit.tasks.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/lean/preset.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/scaffold/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/scaffold/commands/speckit.myext.myextcmd.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/scaffold/commands/speckit.specify.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/scaffold/preset.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/scaffold/templates/myext-template.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/scaffold/templates/spec-template.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/self-test/commands/speckit.specify.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/self-test/commands/speckit.wrap-test.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/self-test/preset.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/self-test/templates/checklist-template.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/self-test/templates/constitution-template.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/self-test/templates/plan-template.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/self-test/templates/spec-template.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/presets/self-test/templates/tasks-template.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/bash/check-prerequisites.sh +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/bash/create-new-feature.sh +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/bash/resolve-template.sh +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/bash/setup-plan.sh +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/bash/setup-tasks.sh +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/powershell/check-prerequisites.ps1 +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/powershell/common.ps1 +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/powershell/resolve-template.ps1 +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/powershell/setup-plan.ps1 +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/powershell/setup-tasks.ps1 +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/python/check_prerequisites.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/python/common.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/python/create_new_feature.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/python/resolve_template.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/python/setup_plan.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/scripts/python/setup_tasks.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/spec-driven.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/spec-kit.code-workspace +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_agent_config.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_assets.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_console.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_download_security.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_github_http.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_init_options.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_project.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_toml_string.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_utils.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/_version.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/agents.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/authentication/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/authentication/azure_devops.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/authentication/base.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/authentication/github.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/authentication/http.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/commands_impl/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/commands_impl/catalog_config.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/lib/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/lib/project.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/lib/versioning.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/lib/yamlio.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/models/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/models/manifest.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/adapters.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/catalog_stack.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/conflict.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/installer.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/packager.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/primitives.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/references.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/resolver.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/bundler/services/validator.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/catalogs.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/commands/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/commands/bundle/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/commands/event.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/events.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/extensions/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integration_runtime.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integration_scaffold.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integration_state.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integration_status.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/_commands.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/_helpers.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/_install_commands.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/_migrate_commands.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/_query_commands.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/_scaffold_commands.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/agy/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/alquimia/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/amp/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/auggie/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/base.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/bob/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/catalog.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/claude/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/cline/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/codebuddy/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/codex/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/command_code/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/copilot/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/cursor_agent/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/devin/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/docker_agent/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/droid/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/firebender/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/forge/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/gemini/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/generic/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/goose/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/grok/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/hermes/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/junie/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/kilocode/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/kimi/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/kiro_cli/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/lingma/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/manifest.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/omp/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/opencode/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/pi/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/qodercli/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/qwen/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/shai/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/tabnine/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/trae/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/vibe/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/zcode/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/integrations/zed/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/shared_infra.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/base.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/engine.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/overlays/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/overlays/composer.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/overlays/layer_sources.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/overlays/merge.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/command/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/do_while/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/fan_in/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/fan_out/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/gate/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/if_then/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/init/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/prompt/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/shell/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/switch/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/src/specify_cli/workflows/steps/while_loop/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/checklist-template.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/analyze.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/checklist.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/clarify.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/constitution.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/converge.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/implement.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/plan.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/specify.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/tasks.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/commands/taskstoissues.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/constitution-template.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/plan-template.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/spec-template.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/tasks-template.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/templates/vscode-settings.json +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/auth_helpers.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/bundler_helpers.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/conftest.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/contract/test_bundle_cli.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/contract/test_manifest_schema.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/contract/test_wheel_bundled_presets.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/contract/test_wheel_core_pack_scripts.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/assess/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/assess/test_assess_extension.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/bug/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/bug/test_bug_extension.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/git/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/git/test_git_extension.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/git/test_git_extension_python_parity.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/test_agent_context_cli_free.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/test_extension_agent_context.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/test_update_agent_context_feature_json.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/extensions/test_update_agent_context_python_parity.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/hooks/TESTING.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/hooks/plan.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/hooks/spec.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/hooks/tasks.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/http_helpers.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integration/test_bundler_catalog_stack.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integration/test_bundler_init_install.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integration/test_bundler_install_flow.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integration/test_bundler_local_install.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integration/test_bundler_offline.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integration/test_bundler_security_paths.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/__init__.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/conftest.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_base.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_cli.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_events.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_extra_args.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_home_isolation.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_agy.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_alquimia.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_amp.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_auggie.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_base_markdown.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_base_skills.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_base_toml.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_base_yaml.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_bob.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_catalog.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_claude.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_cline.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_codebuddy.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_codex.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_command_code.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_copilot.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_cursor_agent.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_devin.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_docker_agent.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_droid.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_firebender.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_forge.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_gemini.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_generic.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_goose.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_grok.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_hermes.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_junie.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_kilocode.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_kimi.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_kiro_cli.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_lingma.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_omp.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_opencode.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_pi.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_qodercli.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_qwen.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_scaffold.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_shai.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_state.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_subcommand.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_tabnine.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_trae.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_vibe.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_zcode.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_integration_zed.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_manifest.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/integrations/test_skill_frontmatter_quoting.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/self_upgrade_helpers.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_branch_numbering.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_check_prerequisites_paths_only.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_check_prerequisites_python_parity.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_check_tool.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_cli_version.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_command_template_py_scripts.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_commands_package.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_console_imports.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_download_security.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_event_command.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_extension_add_path_traversal.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_extension_registration.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_extension_skills.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_extension_update_hardening.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_github_http.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_github_workflows.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_init_dir.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_init_dir_cli.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_init_output_markup.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_live_transient_windows.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_merge.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_post_process.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_ps1_encoding.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_registrar_path_traversal.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_security_workflow.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_self_upgrade_detection.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_self_upgrade_execution.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_self_upgrade_guidance.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_self_upgrade_verification.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_setup_plan_feature_json.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_setup_plan_no_overwrite.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_setup_plan_python_parity.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_setup_tasks.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_setup_tasks_python_parity.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_shared_infra_gitignore.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_shared_infra_integrity.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_skill_placeholder_py.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_specify_template_numbering.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_timestamp_branches.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_upgrade.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_utils.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_utils_assets_imports.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_version_imports.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/test_workflow_run_without_project.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundle_download_url.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_adapters.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_catalog_config.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_conflict.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_packager.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_primitives.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_references.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_resolver.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_validator.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_versioning.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_bundler_yamlio.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/unit/test_condition_expression_block.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/workflows/conftest.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/workflows/test_overlay_composer.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/workflows/test_overlay_layer_sources.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/workflows/test_overlay_merge.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/workflows/test_overlay_security.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/tests/workflows/test_resolver_integration.py +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/workflows/ARCHITECTURE.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/workflows/PUBLISHING.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/workflows/README.md +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/workflows/catalog.community.json +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/workflows/catalog.json +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/workflows/speckit/workflow.yml +0 -0
- {specify_cli-1.0.3 → specify_cli-1.0.4}/workflows/step-catalog.community.json +0 -0
- {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
|
|
@@ -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
|
|
@@ -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
|
|
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-
|
|
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
|
|
1042
|
+
"description": "Compose project constitutions from shared fragment registries",
|
|
1043
1043
|
"author": "Fyloss",
|
|
1044
|
-
"version": "0.
|
|
1045
|
-
"download_url": "https://github.com/Fyloss/spec-kit-charter/archive/refs/tags/v0.
|
|
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/
|
|
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
|
-
"
|
|
1070
|
-
"
|
|
1071
|
-
"
|
|
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-
|
|
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-
|
|
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
|
|
@@ -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
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
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="$
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
69
|
-
|
|
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=
|
|
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 =
|
|
205
|
-
cid =
|
|
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
|
-
|
|
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(
|
|
1667
|
-
"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
|
-
|
|
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.
|
|
1972
|
-
|
|
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
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
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())
|