specify-cli 1.0.5__tar.gz → 1.0.6__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.6/.github/scripts/check_extension_version_bump.py +232 -0
- specify_cli-1.0.6/.github/skills/code-review/SKILL.md +11 -0
- specify_cli-1.0.6/.github/workflows/extension-version-guard.yml +57 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/stale.yml +5 -5
- {specify_cli-1.0.5 → specify_cli-1.0.6}/CHANGELOG.md +25 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/CONTRIBUTING.md +78 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/PKG-INFO +1 -1
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/community/extensions.md +4 -3
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/reference/core.md +1 -1
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/reference/workflows.md +38 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/EXTENSION-DEVELOPMENT-GUIDE.md +7 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/assess/README.md +23 -1
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/catalog.community.json +89 -34
- {specify_cli-1.0.5 → specify_cli-1.0.6}/newsletters/2026-August.md +3 -3
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/catalog.community.json +6 -6
- {specify_cli-1.0.5 → specify_cli-1.0.6}/pyproject.toml +1 -1
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/agents.py +15 -1
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/services/primitives.py +24 -2
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/events.py +30 -1
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/extensions/__init__.py +3 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/agy/__init__.py +4 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/base.py +50 -1
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/codex/__init__.py +6 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/copilot/__init__.py +9 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/cursor_agent/__init__.py +6 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/devin/__init__.py +6 -0
- specify_cli-1.0.6/src/specify_cli/integrations/docker_agent/__init__.py +204 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/droid/__init__.py +6 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/dsh/__init__.py +6 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/goose/__init__.py +6 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/grok/__init__.py +6 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/hermes/__init__.py +4 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/muse/__init__.py +6 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/omp/__init__.py +6 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/opencode/__init__.py +6 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/rovodev/__init__.py +4 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/presets/__init__.py +2 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/base.py +3 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/engine.py +6 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/steps/command/__init__.py +109 -6
- {specify_cli-1.0.5 → specify_cli-1.0.6}/templates/commands/analyze.md +2 -2
- {specify_cli-1.0.5 → specify_cli-1.0.6}/templates/commands/checklist.md +2 -2
- {specify_cli-1.0.5 → specify_cli-1.0.6}/templates/commands/clarify.md +2 -2
- {specify_cli-1.0.5 → specify_cli-1.0.6}/templates/commands/constitution.md +5 -3
- {specify_cli-1.0.5 → specify_cli-1.0.6}/templates/commands/converge.md +2 -2
- {specify_cli-1.0.5 → specify_cli-1.0.6}/templates/commands/implement.md +2 -2
- {specify_cli-1.0.5 → specify_cli-1.0.6}/templates/commands/plan.md +2 -2
- {specify_cli-1.0.5 → specify_cli-1.0.6}/templates/commands/specify.md +2 -2
- {specify_cli-1.0.5 → specify_cli-1.0.6}/templates/commands/tasks.md +2 -2
- {specify_cli-1.0.5 → specify_cli-1.0.6}/templates/commands/taskstoissues.md +2 -2
- specify_cli-1.0.6/tests/contract/test_bundled_extension_versions.py +83 -0
- specify_cli-1.0.6/tests/contract/test_extension_version_guard_script.py +352 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_base.py +32 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_events.py +192 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_docker_agent.py +145 -0
- specify_cli-1.0.6/tests/test_command_template_hooks.py +80 -0
- specify_cli-1.0.6/tests/test_constitution_template_sync_report.py +25 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_extension_skills.py +46 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_extensions.py +1 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_presets.py +3 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_workflows.py +341 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/unit/test_bundler_primitives.py +72 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/workflows/README.md +33 -0
- specify_cli-1.0.5/src/specify_cli/integrations/docker_agent/__init__.py +0 -126
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.devcontainer/devcontainer.json +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.devcontainer/post-create.sh +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.editorconfig +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.gitattributes +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/CODEOWNERS +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/ISSUE_TEMPLATE/agent_request.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/ISSUE_TEMPLATE/bundle_submission.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/ISSUE_TEMPLATE/extension_submission.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/ISSUE_TEMPLATE/preset_submission.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/aw/actions-lock.json +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/dependabot.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/scripts/check_security_requirements.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/security-audit-requirements.txt +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/skills/add-community-extension/SKILL.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/RELEASE-PROCESS.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/add-community-bundle.lock.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/add-community-bundle.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/add-community-extension.lock.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/add-community-extension.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/add-community-preset.lock.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/add-community-preset.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/bug-assess.lock.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/bug-assess.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/bug-fix.lock.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/bug-fix.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/bug-test.lock.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/bug-test.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/catalog-assign.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/codeql.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/docs.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/feature-assess.lock.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/feature-assess.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/lint.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/publish-pypi.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/release-trigger.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/release.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/security.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.github/workflows/test.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.gitignore +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.markdownlint-cli2.jsonc +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.pre-commit-config.yaml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/.zenodo.json +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/AGENTS.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/CITATION.cff +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/CODE_OF_CONDUCT.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/DEVELOPMENT.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/LICENSE +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/README.zh-CN.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/SECURITY.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/SUPPORT.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/bundles/catalog.community.json +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/.gitignore +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/community/bundles.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/community/friends.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/community/overview.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/community/presets.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/community/walkthroughs.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/concepts/complex-features.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/concepts/sdd.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/concepts/spec-of-specs.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/concepts/spec-persistence.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/docfx.json +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/guides/evolving-specs.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/guides/existing-projects.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/guides/monorepo.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/history.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/images/spec-kit-logo.webp +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/index.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/install/air-gapped.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/install/one-time.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/install/pipx.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/install/pypi.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/install/uv.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/installation.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/local-development.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/quickstart.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/reference/agentic-bugfix.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/reference/agentic-sdd.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/reference/authentication.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/reference/bundles.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/reference/extensions.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/reference/integrations.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/reference/overview.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/reference/presets.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/template/public/main.css +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/toc.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/docs/upgrade.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/examples/bundles/business-analyst/README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/examples/bundles/business-analyst/bundle.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/examples/bundles/developer/README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/examples/bundles/developer/bundle.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/examples/bundles/product-manager/README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/examples/bundles/product-manager/bundle.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/examples/bundles/security-researcher/README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/examples/bundles/security-researcher/bundle.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/EXTENSION-API-REFERENCE.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/EXTENSION-PUBLISHING-GUIDE.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/EXTENSION-USER-GUIDE.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/RFC-EXTENSION-SYSTEM.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/agent-context/README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/agent-context/agent-context-config.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/agent-context/agent-context-defaults.json +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/agent-context/commands/speckit.agent-context.update.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/agent-context/extension.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/agent-context/scripts/bash/update-agent-context.sh +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/agent-context/scripts/powershell/update-agent-context.ps1 +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/agent-context/scripts/python/update_agent_context.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/assess/commands/speckit.assess.decide.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/assess/commands/speckit.assess.define.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/assess/commands/speckit.assess.intake.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/assess/commands/speckit.assess.research.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/assess/commands/speckit.assess.shape.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/assess/extension.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/bug/README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/bug/commands/speckit.bug.assess.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/bug/commands/speckit.bug.fix.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/bug/commands/speckit.bug.test.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/bug/extension.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/catalog.json +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/commands/speckit.git.commit.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/commands/speckit.git.feature.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/commands/speckit.git.initialize.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/commands/speckit.git.remote.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/commands/speckit.git.validate.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/config-template.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/extension.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/git-config.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/scripts/bash/auto-commit.sh +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/scripts/bash/create-new-feature-branch.sh +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/scripts/bash/git-common.sh +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/scripts/bash/initialize-repo.sh +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/scripts/powershell/auto-commit.ps1 +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/scripts/powershell/create-new-feature-branch.ps1 +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/scripts/powershell/git-common.ps1 +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/scripts/powershell/initialize-repo.ps1 +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/scripts/python/auto_commit.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/scripts/python/create_new_feature_branch.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/scripts/python/git_common.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/git/scripts/python/initialize_repo.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/selftest/commands/selftest.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/selftest/extension.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/template/.gitignore +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/template/CHANGELOG.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/template/EXAMPLE-README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/template/LICENSE +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/template/README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/template/commands/example.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/template/config-template.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/extensions/template/extension.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/integrations/CONTRIBUTING.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/integrations/README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/integrations/catalog.community.json +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/integrations/catalog.json +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/media/bootstrap-claude-code.gif +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/media/logo_large.webp +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/media/logo_small.webp +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/media/spec-kit-video-header.jpg +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/media/specify_cli.gif +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/newsletters/2026-April.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/newsletters/2026-February.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/newsletters/2026-July.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/newsletters/2026-June.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/newsletters/2026-March.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/newsletters/2026-May.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/ARCHITECTURE.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/PUBLISHING.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/catalog.json +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/constitution-sync/README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/constitution-sync/commands/speckit.constitution.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/constitution-sync/preset.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/lean/README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/lean/commands/speckit.constitution.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/lean/commands/speckit.implement.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/lean/commands/speckit.plan.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/lean/commands/speckit.specify.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/lean/commands/speckit.tasks.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/lean/preset.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/scaffold/README.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/scaffold/commands/speckit.myext.myextcmd.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/scaffold/commands/speckit.specify.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/scaffold/preset.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/scaffold/templates/myext-template.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/scaffold/templates/spec-template.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/self-test/commands/speckit.specify.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/self-test/commands/speckit.wrap-test.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/self-test/preset.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/self-test/templates/checklist-template.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/self-test/templates/constitution-template.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/self-test/templates/plan-template.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/self-test/templates/spec-template.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/presets/self-test/templates/tasks-template.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/bash/check-prerequisites.sh +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/bash/common.sh +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/bash/create-new-feature.sh +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/bash/resolve-template.sh +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/bash/setup-plan.sh +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/bash/setup-tasks.sh +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/powershell/check-prerequisites.ps1 +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/powershell/common.ps1 +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/powershell/create-new-feature.ps1 +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/powershell/resolve-template.ps1 +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/powershell/setup-plan.ps1 +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/powershell/setup-tasks.ps1 +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/python/check_prerequisites.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/python/common.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/python/create_new_feature.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/python/resolve_template.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/python/setup_plan.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/scripts/python/setup_tasks.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/spec-driven.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/spec-kit.code-workspace +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/_agent_config.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/_assets.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/_console.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/_download_security.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/_github_http.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/_init_options.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/_invocation_style.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/_project.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/_toml_string.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/_utils.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/_version.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/authentication/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/authentication/azure_devops.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/authentication/base.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/authentication/config.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/authentication/github.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/authentication/http.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/commands_impl/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/commands_impl/catalog_config.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/lib/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/lib/project.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/lib/versioning.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/lib/yamlio.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/models/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/models/catalog.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/models/manifest.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/models/records.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/services/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/services/adapters.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/services/catalog_stack.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/services/conflict.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/services/installer.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/services/packager.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/services/references.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/services/resolver.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/bundler/services/validator.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/catalogs.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/commands/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/commands/bundle/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/commands/event.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/commands/init.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/extensions/_commands.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integration_runtime.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integration_scaffold.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integration_state.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integration_status.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/_commands.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/_helpers.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/_install_commands.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/_migrate_commands.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/_query_commands.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/_scaffold_commands.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/alquimia/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/amp/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/auggie/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/bob/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/catalog.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/claude/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/cline/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/codebuddy/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/command_code/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/firebender/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/forge/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/gemini/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/generic/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/junie/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/kilocode/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/kimi/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/kiro_cli/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/lingma/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/manifest.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/pi/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/qodercli/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/qwen/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/shai/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/tabnine/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/trae/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/vibe/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/zcode/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/integrations/zed/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/presets/_commands.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/shared_infra.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/_commands.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/catalog.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/expressions.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/overlays/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/overlays/_commands.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/overlays/composer.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/overlays/layer_sources.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/overlays/merge.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/overlays/schema.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/steps/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/steps/do_while/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/steps/fan_in/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/steps/fan_out/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/steps/gate/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/steps/if_then/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/steps/init/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/steps/prompt/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/steps/shell/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/steps/slot/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/steps/switch/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/src/specify_cli/workflows/steps/while_loop/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/templates/checklist-template.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/templates/constitution-template.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/templates/plan-template.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/templates/spec-template.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/templates/tasks-template.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/templates/vscode-settings.json +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/auth_helpers.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/bundler_helpers.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/conftest.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/contract/test_bundle_cli.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/contract/test_catalog_schema.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/contract/test_manifest_schema.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/contract/test_wheel_bundled_presets.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/contract/test_wheel_core_pack_scripts.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/extensions/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/extensions/assess/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/extensions/assess/test_assess_extension.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/extensions/bug/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/extensions/bug/test_bug_extension.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/extensions/git/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/extensions/git/test_git_extension.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/extensions/git/test_git_extension_python_parity.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/extensions/test_agent_context_cli_free.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/extensions/test_extension_agent_context.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/extensions/test_update_agent_context_feature_json.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/extensions/test_update_agent_context_python_parity.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/hooks/TESTING.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/hooks/plan.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/hooks/spec.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/hooks/tasks.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/http_helpers.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integration/test_bundler_catalog_stack.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integration/test_bundler_init_install.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integration/test_bundler_install_flow.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integration/test_bundler_local_install.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integration/test_bundler_offline.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integration/test_bundler_security_paths.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/__init__.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/conftest.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_cli.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_extra_args.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_home_isolation.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_agy.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_alquimia.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_amp.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_auggie.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_base_markdown.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_base_skills.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_base_toml.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_base_yaml.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_bob.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_catalog.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_claude.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_cline.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_codebuddy.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_codex.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_command_code.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_copilot.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_cursor_agent.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_devin.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_droid.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_dsh.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_firebender.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_forge.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_gemini.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_generic.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_goose.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_grok.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_hermes.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_junie.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_kilocode.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_kimi.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_kiro_cli.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_lingma.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_muse.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_omp.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_opencode.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_pi.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_qodercli.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_qwen.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_rovodev.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_scaffold.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_shai.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_state.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_subcommand.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_tabnine.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_trae.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_vibe.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_zcode.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_integration_zed.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_manifest.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_registry.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/integrations/test_skill_frontmatter_quoting.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/parity_helpers.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/self_upgrade_helpers.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_agent_config_consistency.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_authentication.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_branch_numbering.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_check_prerequisites_paths_only.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_check_prerequisites_python_parity.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_check_tool.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_cli_version.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_command_template_py_scripts.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_commands_package.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_console_imports.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_create_new_feature_python_parity.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_download_security.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_event_command.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_extension_add_path_traversal.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_extension_content_staleness.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_extension_registration.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_extension_update_hardening.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_github_http.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_github_workflows.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_init_dir.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_init_dir_cli.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_init_output_markup.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_live_transient_windows.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_merge.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_post_process.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_ps1_encoding.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_registrar_path_traversal.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_resolve_template_python_parity.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_security_workflow.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_self_upgrade_detection.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_self_upgrade_execution.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_self_upgrade_guidance.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_self_upgrade_verification.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_setup_plan_feature_json.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_setup_plan_no_overwrite.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_setup_plan_python_parity.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_setup_tasks.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_setup_tasks_python_parity.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_shared_infra_gitignore.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_shared_infra_integrity.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_skill_placeholder_py.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_specify_template_numbering.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_tasks_template_constraints.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_timestamp_branches.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_upgrade.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_utils.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_utils_assets_imports.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_version_imports.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/test_workflow_run_without_project.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/unit/test_bundle_download_url.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/unit/test_bundler_adapters.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/unit/test_bundler_catalog_config.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/unit/test_bundler_conflict.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/unit/test_bundler_packager.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/unit/test_bundler_records.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/unit/test_bundler_references.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/unit/test_bundler_resolver.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/unit/test_bundler_validator.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/unit/test_bundler_versioning.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/unit/test_bundler_yamlio.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/unit/test_condition_expression_block.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/workflows/conftest.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/workflows/test_bundled_speckit_workflow.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/workflows/test_overlay_commands.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/workflows/test_overlay_composer.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/workflows/test_overlay_layer_sources.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/workflows/test_overlay_merge.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/workflows/test_overlay_schema.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/workflows/test_overlay_security.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/workflows/test_resolver_integration.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/tests/workflows/test_slot_step.py +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/workflows/ARCHITECTURE.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/workflows/PUBLISHING.md +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/workflows/catalog.community.json +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/workflows/catalog.json +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/workflows/speckit/workflow.yml +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/workflows/step-catalog.community.json +0 -0
- {specify_cli-1.0.5 → specify_cli-1.0.6}/workflows/step-catalog.json +0 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Fail a PR that changes bundled extension content without a version bump.
|
|
3
|
+
|
|
4
|
+
Update offers from `specify extension update` are version-driven: an
|
|
5
|
+
extension is offered (and installed) only when the semver in
|
|
6
|
+
`extensions/catalog.json` exceeds the installed copy's registered
|
|
7
|
+
version. A content change shipped without a version bump is therefore
|
|
8
|
+
never delivered automatically (#4345) — a bump is what makes a change
|
|
9
|
+
actually reach existing installs, and this guard is what makes the bump
|
|
10
|
+
non-optional.
|
|
11
|
+
|
|
12
|
+
This check enforces two invariants on the extensions listed in
|
|
13
|
+
`extensions/catalog.json`:
|
|
14
|
+
|
|
15
|
+
1. Any change to a file under `extensions/<id>/` must increase the
|
|
16
|
+
`version:` in that extension's `extension.yml` (PEP 440 comparison,
|
|
17
|
+
the same semantics `extension update` uses), and the resulting
|
|
18
|
+
version must itself parse as PEP 440 — including for a brand-new
|
|
19
|
+
extension, since the CLI rejects a manifest whose version it cannot
|
|
20
|
+
parse.
|
|
21
|
+
2. Every `version` in `extensions/catalog.json` must parse as PEP 440
|
|
22
|
+
(`extension update` skips entries it cannot parse), and for entries
|
|
23
|
+
with an in-repo directory it must equal a likewise-valid
|
|
24
|
+
`extension.version` in the manifest (the catalog is what update
|
|
25
|
+
checks compare against, and the update preflight rejects a manifest
|
|
26
|
+
whose version differs from the catalog's). This runs over every
|
|
27
|
+
catalog entry, so catalog-only (hosted) entries and catalog-only
|
|
28
|
+
promotions of existing directories are covered too.
|
|
29
|
+
|
|
30
|
+
Usage:
|
|
31
|
+
check_extension_version_bump.py BASE_REF [HEAD_REF]
|
|
32
|
+
|
|
33
|
+
BASE_REF is a git ref/SHA for the PR base (must be fetchable with
|
|
34
|
+
`git show`). HEAD_REF defaults to the working tree's HEAD. Exits 0 when
|
|
35
|
+
all invariants hold, 1 otherwise, printing one line per violation.
|
|
36
|
+
|
|
37
|
+
Extensions under `extensions/` that are not in the catalog (the
|
|
38
|
+
`selftest` fixture and the `template` scaffold) are exempt: no update
|
|
39
|
+
flow is driven by their versions.
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
from __future__ import annotations
|
|
43
|
+
|
|
44
|
+
import json
|
|
45
|
+
import subprocess
|
|
46
|
+
import sys
|
|
47
|
+
from pathlib import PurePosixPath
|
|
48
|
+
|
|
49
|
+
import yaml
|
|
50
|
+
from packaging.version import InvalidVersion, Version
|
|
51
|
+
|
|
52
|
+
EXTENSIONS_ROOT = "extensions"
|
|
53
|
+
CATALOG_PATH = f"{EXTENSIONS_ROOT}/catalog.json"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _changed_paths(base_ref: str, head_ref: str) -> list[str]:
|
|
57
|
+
"""Paths under extensions/ that differ between *base_ref* and *head_ref*.
|
|
58
|
+
|
|
59
|
+
Uses NUL-delimited output (``-z``): without it git C-quotes any path
|
|
60
|
+
containing non-ASCII or control characters (``"extensions/x/caf\\303\\251"``,
|
|
61
|
+
quotes included), so the leading component would no longer equal
|
|
62
|
+
``extensions`` and that change would silently escape the guard. Paths
|
|
63
|
+
are decoded with surrogateescape so an undecodable byte can never crash
|
|
64
|
+
the check; only the ASCII ``extensions/<id>/`` prefix is interpreted.
|
|
65
|
+
"""
|
|
66
|
+
raw = subprocess.run(
|
|
67
|
+
[
|
|
68
|
+
"git", "diff", "--name-only", "-z", "--no-renames",
|
|
69
|
+
base_ref, head_ref, "--", EXTENSIONS_ROOT,
|
|
70
|
+
],
|
|
71
|
+
check=True,
|
|
72
|
+
capture_output=True,
|
|
73
|
+
).stdout
|
|
74
|
+
return [
|
|
75
|
+
chunk.decode("utf-8", errors="surrogateescape")
|
|
76
|
+
for chunk in raw.split(b"\0")
|
|
77
|
+
if chunk
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def _show(ref: str, path: str) -> str | None:
|
|
82
|
+
"""Return the file's content at *ref*, or None when absent there."""
|
|
83
|
+
result = subprocess.run(
|
|
84
|
+
["git", "show", f"{ref}:{path}"], capture_output=True, text=True
|
|
85
|
+
)
|
|
86
|
+
return result.stdout if result.returncode == 0 else None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _manifest_version(manifest_text: str, origin: str) -> str:
|
|
90
|
+
data = yaml.safe_load(manifest_text)
|
|
91
|
+
if not isinstance(data, dict) or not isinstance(data.get("extension"), dict):
|
|
92
|
+
raise ValueError(f"{origin}: manifest is not a mapping with an 'extension' block")
|
|
93
|
+
version = data["extension"].get("version")
|
|
94
|
+
if not isinstance(version, str) or not version.strip():
|
|
95
|
+
raise ValueError(f"{origin}: extension.version is missing or not a string")
|
|
96
|
+
return version.strip()
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def main(argv: list[str]) -> int:
|
|
100
|
+
if len(argv) < 2 or len(argv) > 3:
|
|
101
|
+
print(__doc__, file=sys.stderr)
|
|
102
|
+
return 2
|
|
103
|
+
base_ref = argv[1]
|
|
104
|
+
head_ref = argv[2] if len(argv) == 3 else "HEAD"
|
|
105
|
+
|
|
106
|
+
catalog_text = _show(head_ref, CATALOG_PATH)
|
|
107
|
+
if catalog_text is None:
|
|
108
|
+
print(f"::error::{CATALOG_PATH} is missing at {head_ref}")
|
|
109
|
+
return 1
|
|
110
|
+
catalog = json.loads(catalog_text)
|
|
111
|
+
catalog_entries = catalog.get("extensions", {})
|
|
112
|
+
|
|
113
|
+
errors: list[str] = []
|
|
114
|
+
|
|
115
|
+
# -- Invariant 1: content change requires a version bump ---------------
|
|
116
|
+
changed_ids = {
|
|
117
|
+
parts[1]
|
|
118
|
+
for path in _changed_paths(base_ref, head_ref)
|
|
119
|
+
if len(parts := PurePosixPath(path).parts) >= 3 and parts[0] == EXTENSIONS_ROOT
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
for ext_id in sorted(changed_ids):
|
|
123
|
+
if ext_id not in catalog_entries:
|
|
124
|
+
continue # not driven by `extension update` (selftest, template)
|
|
125
|
+
manifest_path = f"{EXTENSIONS_ROOT}/{ext_id}/extension.yml"
|
|
126
|
+
head_manifest = _show(head_ref, manifest_path)
|
|
127
|
+
if head_manifest is None:
|
|
128
|
+
continue # extension removed in this PR
|
|
129
|
+
try:
|
|
130
|
+
head_version = _manifest_version(head_manifest, f"{head_ref}:{manifest_path}")
|
|
131
|
+
except ValueError as exc:
|
|
132
|
+
errors.append(str(exc))
|
|
133
|
+
continue
|
|
134
|
+
|
|
135
|
+
# Parse the head version before the new-extension early return: the
|
|
136
|
+
# CLI's ExtensionManifest rejects a version packaging cannot parse and
|
|
137
|
+
# `extension update` skips catalog entries whose version is invalid,
|
|
138
|
+
# so a new extension shipped with e.g. "not-a-version" in both places
|
|
139
|
+
# would be uninstallable even though the catalog check below (plain
|
|
140
|
+
# string equality) passes. Same PEP 440 semantics as the CLI, so
|
|
141
|
+
# prereleases and other accepted forms are handled identically.
|
|
142
|
+
try:
|
|
143
|
+
head_parsed = Version(head_version)
|
|
144
|
+
except InvalidVersion as exc:
|
|
145
|
+
errors.append(
|
|
146
|
+
f"{manifest_path}: extension.version {head_version!r} is not a valid "
|
|
147
|
+
f"PEP 440 version ({exc}); the CLI rejects this manifest."
|
|
148
|
+
)
|
|
149
|
+
continue
|
|
150
|
+
|
|
151
|
+
base_manifest = _show(base_ref, manifest_path)
|
|
152
|
+
if base_manifest is None:
|
|
153
|
+
continue # new extension; any valid initial version is fine
|
|
154
|
+
try:
|
|
155
|
+
base_version = _manifest_version(base_manifest, f"{base_ref}:{manifest_path}")
|
|
156
|
+
except ValueError as exc:
|
|
157
|
+
errors.append(str(exc))
|
|
158
|
+
continue
|
|
159
|
+
|
|
160
|
+
# Compare with the same PEP 440 semantics the extension update and
|
|
161
|
+
# install code use, so prereleases and other accepted forms cannot
|
|
162
|
+
# bypass the guard (e.g. 2.0.0 -> 1.0.0rc1 is a downgrade). An
|
|
163
|
+
# unparseable base version fails closed.
|
|
164
|
+
try:
|
|
165
|
+
base_parsed = Version(base_version)
|
|
166
|
+
except InvalidVersion as exc:
|
|
167
|
+
errors.append(
|
|
168
|
+
f"{manifest_path}: could not compare versions "
|
|
169
|
+
f"{base_version!r} -> {head_version!r}: {exc}"
|
|
170
|
+
)
|
|
171
|
+
continue
|
|
172
|
+
if head_parsed <= base_parsed:
|
|
173
|
+
errors.append(
|
|
174
|
+
f"{manifest_path}: files under {EXTENSIONS_ROOT}/{ext_id}/ changed but "
|
|
175
|
+
f"extension.version did not increase ({base_version} -> {head_version}). "
|
|
176
|
+
f"Installed copies only receive changes when the version is bumped."
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# -- Invariant 2: catalog versions are valid and match the manifests ----
|
|
180
|
+
# Runs over every catalog entry, changed or not: a catalog-only entry
|
|
181
|
+
# (hosted elsewhere) never has files under extensions/<id>/, and a
|
|
182
|
+
# catalog-only promotion of an existing uncataloged directory never
|
|
183
|
+
# enters Invariant 1, so neither would otherwise have its version parsed.
|
|
184
|
+
for ext_id, entry in sorted(catalog_entries.items()):
|
|
185
|
+
catalog_version = entry.get("version") if isinstance(entry, dict) else None
|
|
186
|
+
if not isinstance(catalog_version, str) or not catalog_version.strip():
|
|
187
|
+
errors.append(f"{CATALOG_PATH}: entry '{ext_id}' has no string 'version'")
|
|
188
|
+
continue
|
|
189
|
+
# `extension update` skips a catalog entry whose version packaging
|
|
190
|
+
# cannot parse, so an invalid catalog version is never offered.
|
|
191
|
+
try:
|
|
192
|
+
Version(catalog_version)
|
|
193
|
+
except InvalidVersion as exc:
|
|
194
|
+
errors.append(
|
|
195
|
+
f"{CATALOG_PATH}: entry '{ext_id}' version {catalog_version!r} is not a "
|
|
196
|
+
f"valid PEP 440 version ({exc}); `extension update` skips such entries."
|
|
197
|
+
)
|
|
198
|
+
continue
|
|
199
|
+
|
|
200
|
+
manifest_path = f"{EXTENSIONS_ROOT}/{ext_id}/extension.yml"
|
|
201
|
+
head_manifest = _show(head_ref, manifest_path)
|
|
202
|
+
if head_manifest is None:
|
|
203
|
+
continue # catalog-only entry (e.g. hosted elsewhere); version checked above
|
|
204
|
+
try:
|
|
205
|
+
manifest_version = _manifest_version(head_manifest, f"{head_ref}:{manifest_path}")
|
|
206
|
+
except ValueError as exc:
|
|
207
|
+
errors.append(str(exc))
|
|
208
|
+
continue
|
|
209
|
+
try:
|
|
210
|
+
Version(manifest_version)
|
|
211
|
+
except InvalidVersion as exc:
|
|
212
|
+
errors.append(
|
|
213
|
+
f"{manifest_path}: extension.version {manifest_version!r} is not a valid "
|
|
214
|
+
f"PEP 440 version ({exc}); the CLI rejects this manifest."
|
|
215
|
+
)
|
|
216
|
+
continue
|
|
217
|
+
if catalog_version != manifest_version:
|
|
218
|
+
errors.append(
|
|
219
|
+
f"{CATALOG_PATH}: entry '{ext_id}' has version {catalog_version!r} but "
|
|
220
|
+
f"{manifest_path} declares {manifest_version!r}. `extension update` "
|
|
221
|
+
f"compares against the catalog, so the two must move together."
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
for error in errors:
|
|
225
|
+
print(f"::error::{error}")
|
|
226
|
+
if not errors:
|
|
227
|
+
print("Extension version guard: all invariants hold.")
|
|
228
|
+
return 1 if errors else 0
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
if __name__ == "__main__":
|
|
232
|
+
sys.exit(main(sys.argv))
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: code-review
|
|
3
|
+
description: Reviews Spec Kit code changes for positive and negative test coverage, regression evidence for bug fixes, and consistent repository terminology. Use when reviewing a diff or pull request. Do not use for implementing changes or posting GitHub review actions.
|
|
4
|
+
argument-hint: 'Diff or pull request to review'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Code Review
|
|
8
|
+
|
|
9
|
+
1. Ensure each code change has test cases that verify what the code should do and what it should prevent.
|
|
10
|
+
2. Ensure bug-fix pull requests include a regression test that demonstrates the bug was reproducible before the change and is fixed afterward; if the reviewer cannot run the comparison, use available evidence and state that limitation.
|
|
11
|
+
3. Ensure wording changes use repository-consistent terms; exclude community-authored catalog content and its generated documentation from this check.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: Extension Version Guard
|
|
2
|
+
|
|
3
|
+
permissions:
|
|
4
|
+
contents: read
|
|
5
|
+
|
|
6
|
+
# Bundled extensions only reach existing installs through a version bump:
|
|
7
|
+
# `specify extension update` compares the semver in extensions/catalog.json
|
|
8
|
+
# against the installed copy and reports "Up to date" whenever they match.
|
|
9
|
+
# Content changes shipped without a bump go silently stale on every
|
|
10
|
+
# project that already installed the extension (#4345). This guard turns
|
|
11
|
+
# "please remember to bump" into a merge requirement.
|
|
12
|
+
#
|
|
13
|
+
# Deliberately no `paths:` filter: a required status check that is skipped
|
|
14
|
+
# by path filtering stays in "Expected" state and blocks every PR that does
|
|
15
|
+
# not touch extensions/**. The check runs on every pull request instead and
|
|
16
|
+
# the script reports success when nothing under extensions/ changed.
|
|
17
|
+
on:
|
|
18
|
+
pull_request:
|
|
19
|
+
|
|
20
|
+
jobs:
|
|
21
|
+
version-bump:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- name: Checkout
|
|
25
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
26
|
+
with:
|
|
27
|
+
# The pull_request checkout is GitHub's merge of the PR head into
|
|
28
|
+
# the base tip. Depth 2 also fetches both parents of that merge
|
|
29
|
+
# commit, so HEAD^1 - the base the merge was actually built on -
|
|
30
|
+
# is available to diff against.
|
|
31
|
+
fetch-depth: 2
|
|
32
|
+
|
|
33
|
+
- name: Set up Python
|
|
34
|
+
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
|
|
35
|
+
with:
|
|
36
|
+
python-version: "3.14"
|
|
37
|
+
|
|
38
|
+
- name: Install check dependencies
|
|
39
|
+
run: python -m pip install --quiet pyyaml packaging
|
|
40
|
+
|
|
41
|
+
# Diff against the merge commit's first parent, NOT against
|
|
42
|
+
# github.event.pull_request.base.sha. The payload SHA is the base tip
|
|
43
|
+
# from when the PR was opened and is not refreshed when the base branch
|
|
44
|
+
# moves, while refs/pull/N/merge is rebuilt against the current tip.
|
|
45
|
+
# Diffing the stale SHA against the fresh merge commit attributes
|
|
46
|
+
# unrelated base-branch drift to the PR (observed on #4395: two
|
|
47
|
+
# unbumped extension changes merged to main were blamed on a PR that
|
|
48
|
+
# never touched them). HEAD^1 is by construction the base the merge
|
|
49
|
+
# was built on.
|
|
50
|
+
- name: Check bundled extension version bumps
|
|
51
|
+
run: |
|
|
52
|
+
set -euo pipefail
|
|
53
|
+
if ! git rev-parse --verify --quiet HEAD^2 >/dev/null; then
|
|
54
|
+
echo "::error::HEAD is not the pull request merge commit; cannot determine the PR base"
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
python .github/scripts/check_extension_version_bump.py HEAD^1
|
|
@@ -17,18 +17,18 @@ jobs:
|
|
|
17
17
|
- uses: actions/stale@4391f3da665fdf50b6810c1a66712fb9ba21aa93 # v11.0.0
|
|
18
18
|
with:
|
|
19
19
|
# Days of inactivity before an issue or PR becomes stale
|
|
20
|
-
days-before-stale:
|
|
20
|
+
days-before-stale: 60
|
|
21
21
|
# Days of inactivity before a stale issue or PR is closed (after being marked stale)
|
|
22
22
|
days-before-close: 30
|
|
23
23
|
|
|
24
24
|
# Stale issue settings
|
|
25
|
-
stale-issue-message: 'This issue has been automatically marked as stale because it has not had any activity for
|
|
26
|
-
close-issue-message: 'This issue has been automatically closed due to inactivity (
|
|
25
|
+
stale-issue-message: 'This issue has been automatically marked as stale because it has not had any activity for 60 days. It will be closed in 30 days if no further activity occurs.'
|
|
26
|
+
close-issue-message: 'This issue has been automatically closed due to inactivity (90 days total). If you believe this issue is still relevant, please reopen it or create a new issue.'
|
|
27
27
|
stale-issue-label: 'stale'
|
|
28
28
|
|
|
29
29
|
# Stale PR settings
|
|
30
|
-
stale-pr-message: 'This pull request has been automatically marked as stale because it has not had any activity for
|
|
31
|
-
close-pr-message: 'This pull request has been automatically closed due to inactivity (
|
|
30
|
+
stale-pr-message: 'This pull request has been automatically marked as stale because it has not had any activity for 60 days. It will be closed in 30 days if no further activity occurs.'
|
|
31
|
+
close-pr-message: 'This pull request has been automatically closed due to inactivity (90 days total). If you believe this PR is still relevant, please reopen it or create a new PR.'
|
|
32
32
|
stale-pr-label: 'stale'
|
|
33
33
|
|
|
34
34
|
# Exempt issues and PRs with these labels from being marked as stale
|
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- insert new changelog below this comment -->
|
|
4
4
|
|
|
5
|
+
## [1.0.6] - 2026-09-10
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- fix(events): cap stdin in the generated dispatcher, not just the CLI command (#4337)
|
|
10
|
+
- docs(core): SPECIFY_FEATURE sets the feature label, not the feature directory (#3786)
|
|
11
|
+
- chore: shorten stale timeline to 60 days stale, 30 days to close (#4503)
|
|
12
|
+
- [extension] Update Spec Kit Schedule extension to v0.7.4 (#4498)
|
|
13
|
+
- [preset] Update Inventory Alignment preset to v0.1.1 (#4494)
|
|
14
|
+
- Update Spec Inventory extension to v0.1.1 (#4496)
|
|
15
|
+
- docs: document contribution evidence gate and label taxonomy (#4478)
|
|
16
|
+
- feat(workflows): add per-step integration configuration (#4425)
|
|
17
|
+
- fix: preserve extension authors in generated skills (#4459)
|
|
18
|
+
- Add ProductShape PRODUCT workflows extension to community catalog (#4485)
|
|
19
|
+
- Update AgentPay x402 extension to v1.1.0 (#4482)
|
|
20
|
+
- Update Figma Starter extension to v1.1.0 (#4490)
|
|
21
|
+
- Fix #4345 (3/4): CI guard requiring version bumps on bundled extension changes (#4395)
|
|
22
|
+
- fix(templates): report an unreadable extensions.yml instead of skipping hooks silently (#4456)
|
|
23
|
+
- Add concise code review skill (#4471)
|
|
24
|
+
- docs(templates): clarify /constitution's Sync Impact Report is temporary, review-only material (#4431) (#4432)
|
|
25
|
+
- fix(bundler): re-read the step registry when rolling back a failed step refresh (#4139)
|
|
26
|
+
- Fix August newsletter review findings (#4444)
|
|
27
|
+
- docs: resolve assess clarifications by editing artifacts in place (#4402)
|
|
28
|
+
- chore: release 1.0.5, begin 1.0.6.dev0 development (#4479)
|
|
29
|
+
|
|
5
30
|
## [1.0.5] - 2026-09-08
|
|
6
31
|
|
|
7
32
|
### Changed
|
|
@@ -57,6 +57,84 @@ Here are a few things you can do that will increase the likelihood of your pull
|
|
|
57
57
|
|
|
58
58
|
Accounts with three open pull requests may continue submitting changes, but additional submissions may be placed behind contributions from other authors in the review queue. Coding agents should disclose this possibility and obtain the filer's confirmation before opening another pull request.
|
|
59
59
|
|
|
60
|
+
### Evidence gate
|
|
61
|
+
|
|
62
|
+
A contribution is evaluated on the evidence it carries, not on how plausible its reasoning sounds. The same bar applies to everyone — human and AI-assisted contributions are judged identically.
|
|
63
|
+
|
|
64
|
+
A valid, in-scope change that arrives without evidence is not rejected outright. It may be labeled [`triage-can-wait`](#triage-and-author-labels) and held behind proven work until evidence is added, at which point it can be reprioritized.
|
|
65
|
+
|
|
66
|
+
What counts as evidence:
|
|
67
|
+
|
|
68
|
+
- **A reproduction or a linked real-world report** — a failing case, a stack trace, or a link to an issue where the problem actually occurred. "This could theoretically fail" reasoning on its own does not clear the gate.
|
|
69
|
+
- **A regression test that fails on `main` and passes with your change** — this proves both that the problem is real and that your change fixes it.
|
|
70
|
+
- **Scope discipline** — one concern per pull request. Split unrelated changes into separate PRs (see the [focused-change guidance](#submitting-a-pull-request) above); sprawling batch diffs are hard to review and slow to land.
|
|
71
|
+
- **Disclosed AI assistance** — if any AI tooling was involved, disclose it and its extent per [AI contributions in Spec Kit](#ai-contributions-in-spec-kit).
|
|
72
|
+
|
|
73
|
+
Speculative hardening is welcome, but it sits behind proven, evidence-backed work. If you can attach a reproduction and a failing test, your change moves to the front; if you can't yet, say so, and it will be queued rather than closed.
|
|
74
|
+
|
|
75
|
+
### Review rubric
|
|
76
|
+
|
|
77
|
+
Triaged items are weighed across seven dimensions, each scored `0`–`2` (`0` absent, `1` partial, `2` clearly demonstrated), for a maximum of 14. The score guides **prioritization** — it is not a hard pass/fail gate. The one firm rule is the [evidence gate](#evidence-gate) above: theoretical-only changes with no evidence are deprioritized.
|
|
78
|
+
|
|
79
|
+
| Dimension | What it measures |
|
|
80
|
+
|---|---|
|
|
81
|
+
| D1 — Real-world evidence | A reproduction or linked report, versus theory alone |
|
|
82
|
+
| D2 — Reachability / severity | Whether the issue can actually be hit, and how bad it is |
|
|
83
|
+
| D3 — Scope discipline | One focused concern per PR, no unrelated changes |
|
|
84
|
+
| D4 — Test evidence | A regression test that fails on `main` and passes with the change |
|
|
85
|
+
| D5 — Disclosure / understanding | AI use disclosed, and the author understands the change |
|
|
86
|
+
| D6 — Cost vs. benefit | Value delivered against added complexity and maintenance cost |
|
|
87
|
+
| D7 — Roadmap alignment | Fit with Spec Kit's goals and direction |
|
|
88
|
+
|
|
89
|
+
### Triage and author labels
|
|
90
|
+
|
|
91
|
+
Every triaged item receives one **verdict** label recording where it stands. **Author** labels signal the specific action needed to move an item forward.
|
|
92
|
+
|
|
93
|
+
Verdict (one per item):
|
|
94
|
+
|
|
95
|
+
| Label | Meaning |
|
|
96
|
+
|---|---|
|
|
97
|
+
| `triage-must-have` | Verdict: high-value, important work for Spec Kit — do first |
|
|
98
|
+
| `triage-nice-to-have` | Verdict: evidence-backed fix or greenlit feature — land after review |
|
|
99
|
+
| `triage-can-wait` | Verdict: valid and in-scope but deprioritized; held behind the evidence gate |
|
|
100
|
+
| `triage-out-of-scope` | Verdict: won't land in core — invalid, duplicate, off-mission, or redirected to an extension |
|
|
101
|
+
|
|
102
|
+
Author actions:
|
|
103
|
+
|
|
104
|
+
| Label | Meaning |
|
|
105
|
+
|---|---|
|
|
106
|
+
| `author-needs-proof` | The problem isn't demonstrated yet — supply a reproduction or a test that fails on `main` and passes with the change |
|
|
107
|
+
| `author-needs-tests` | Real change but missing a regression test — add one that fails before / passes after |
|
|
108
|
+
| `author-needs-rescope` | Sprawling or batched diff — split into one focused, single-concern PR |
|
|
109
|
+
| `author-needs-disclosure` | AI assistance not disclosed — disclose AI use per CONTRIBUTING |
|
|
110
|
+
| `author-needs-info` | Missing detail needed to assess — supply requested info |
|
|
111
|
+
| `author-needs-rebase` | Branch conflicts with `main` — rebase and resolve before it can be merged |
|
|
112
|
+
| `author-over-cap` | Over the 3-open-PR cap or repetitive batch submissions — please consolidate |
|
|
113
|
+
| `author-awaiting` | Waiting on author response (handed off to the existing stale workflow) |
|
|
114
|
+
|
|
115
|
+
Some pull requests are closed as `triage-out-of-scope` rather than merged — most commonly
|
|
116
|
+
when the same change is already in `main`, when a request is better served as a community
|
|
117
|
+
extension, when an existing feature already covers it, or when a catalog change came in as
|
|
118
|
+
a direct edit instead of a submission issue. A close always comes with a comment explaining
|
|
119
|
+
why and, where relevant, where to go instead.
|
|
120
|
+
|
|
121
|
+
For further reading on the thinking behind this gate, see [one maintainer's perspective on AI-sourced contributions](https://blog.manorrock.com/blog/2026/09/08/spec_kit_ai_source.html). That piece is a personal viewpoint, not project policy — the policy is what's documented here.
|
|
122
|
+
|
|
123
|
+
### Community catalog submissions
|
|
124
|
+
|
|
125
|
+
To add or update a community extension, preset, or bundle in the catalog, **open an
|
|
126
|
+
`[Extension]` / `[Preset]` / `[Bundle]` submission issue** — do not edit
|
|
127
|
+
`extensions/catalog.community.json` (or the preset/bundle catalogs) directly in a pull
|
|
128
|
+
request. The submission issue triggers an automated workflow that validates the release,
|
|
129
|
+
verifies the pinned `download_url` and digests, and generates the catalog PR for you.
|
|
130
|
+
A hand-edited catalog PR bypasses that validation and will be closed with a pointer back
|
|
131
|
+
to the issue flow.
|
|
132
|
+
|
|
133
|
+
This applies to **new entries, version updates, and repairs alike** — a version bump or a
|
|
134
|
+
fix to a broken entry is still an update and needs the same validation. Always pin
|
|
135
|
+
`download_url` to a release tag (e.g. `.../releases/download/<tag>/...` or
|
|
136
|
+
`.../archive/refs/tags/<tag>.zip`); never use `releases/latest/`.
|
|
137
|
+
|
|
60
138
|
### Branch naming
|
|
61
139
|
|
|
62
140
|
We recommend naming branches as `<type>/<number>-<short-slug>`, where `<number>` is the issue or PR number (whichever comes first) and `<type>` is one of:
|
|
@@ -30,7 +30,7 @@ The following community-contributed extensions are available in [`catalog.commun
|
|
|
30
30
|
| Agent Governance | Generate agent-platform repository governance files from Spec Kit metadata | `process` | Read+Write | [spec-kit-agent-governance](https://github.com/bigsmartben/spec-kit-agent-governance) |
|
|
31
31
|
| AgentDocx | Full-stack multi-agent specification pipeline with VS Code extension control, automated Kanban/Jira sync, and React monitoring dashboard | `integration` | Read+Write | [extension-github-spec-kit](https://github.com/abir-ommezzine/extension-github-spec-kit) |
|
|
32
32
|
| AgentDocx SpecKit V2 | AgentDocx evolved: same pipeline + far more autonomous Ticket Manager (5 CLI, per-project Kanban, bulk sync, auto-switch, Auditor) | `integration` | Read+Write | [Extension_GithubSpecKit](https://github.com/ahmed200346/Extension_GithubSpecKit) |
|
|
33
|
-
| AgentPay x402 — Spend Controls for Spec Kit Agents | Set USDC spending caps
|
|
33
|
+
| AgentPay x402 — Spend Controls for Spec Kit Agents | Set USDC spending caps, check a counterparty's credit before paying it, and pay x402-enabled APIs during spec implementation. Settles on Base or Solana. | `integration` | Read+Write | [spec-kit-pay-x402](https://github.com/shawnhvac/spec-kit-pay-x402) |
|
|
34
34
|
| AI-Driven Engineering (AIDE) | A structured 7-step workflow for building new projects from scratch with AI assistants — from vision through implementation | `process` | Read+Write | [aide](https://github.com/mnriem/spec-kit-extensions/tree/main/aide) |
|
|
35
35
|
| Analytics | Measure what your AI builds, and how much time it saves you | `visibility` | Read+Write | [spec-kit-analytics](https://github.com/Fyloss/spec-kit-analytics) |
|
|
36
36
|
| API Evolve | Managed API contract evolution — breaking-change detection, semver enforcement, deprecation orchestration, and lifecycle gates across REST, GraphQL, and gRPC | `process` | Read+Write | [spec-kit-api-evolve](https://github.com/Quratulain-bilal/spec-kit-api-evolve) |
|
|
@@ -69,7 +69,7 @@ The following community-contributed extensions are available in [`catalog.commun
|
|
|
69
69
|
| EARS Requirements Syntax | Author, lint, and convert requirements using EARS - the five industry-standard sentence patterns for unambiguous, testable requirements | `docs` | Read+Write | [spec-kit-ears](https://github.com/dhruv-15-03/spec-kit-ears) |
|
|
70
70
|
| Evaluator Contract | Provider-neutral evaluator contract for evidence, provenance, uncertainty, and recovery across Spec-Driven Development phases. | `process` | Read+Write | [spec-kit-evaluator](https://github.com/electrohire/spec-kit-evaluator) |
|
|
71
71
|
| Extensify | Create and validate extensions and extension catalogs | `process` | Read+Write | [extensify](https://github.com/mnriem/spec-kit-extensions/tree/main/extensify) |
|
|
72
|
-
| Figma Starter | Turns a Figma section's screens into
|
|
72
|
+
| Figma Starter | Turns a Figma section's screens into Figma-derived specs, and an OpenAPI/Swagger document into an entity model plus per-page UI-to-API bindings, then hands off to /speckit.specify | `docs` | Read+Write | [spec-kit-figma-starter](https://github.com/OmneWave/spec-kit-figma-starter) |
|
|
73
73
|
| Fix Findings | Automated analyze-fix-reanalyze loop that resolves spec findings until clean | `code` | Read+Write | [spec-kit-fix-findings](https://github.com/Quratulain-bilal/spec-kit-fix-findings) |
|
|
74
74
|
| FixIt Extension | Spec-aware bug fixing — maps bugs to spec artifacts, proposes a plan, applies minimal changes | `code` | Read+Write | [spec-kit-fixit](https://github.com/speckit-community/spec-kit-fixit) |
|
|
75
75
|
| Fleet Orchestrator | Orchestrate a full feature lifecycle with human-in-the-loop gates across all SpecKit phases | `process` | Read+Write | [spec-kit-fleet](https://github.com/sharathsatish/spec-kit-fleet) |
|
|
@@ -119,6 +119,7 @@ The following community-contributed extensions are available in [`catalog.commun
|
|
|
119
119
|
| Presetify | Create and validate presets and preset catalogs | `process` | Read+Write | [presetify](https://github.com/mnriem/spec-kit-extensions/tree/main/presetify) |
|
|
120
120
|
| Product Forge | Full product-lifecycle orchestrator for Spec Kit: research → product-spec → plan → tasks → implement → verify → test → release-readiness, across express/lite/standard/v-model modes with human-in-the-loop gates. | `process` | Read+Write | [speckit-product-forge](https://github.com/VaiYav/speckit-product-forge) |
|
|
121
121
|
| Product Spec Extension | Generates PRFAQ, Lean PRD, stakeholder summaries, and technical designs from engineering specs | `docs` | Read+Write | [spec-kit-product](https://github.com/d0whc3r/spec-kit-product) |
|
|
122
|
+
| ProductShape PRODUCT workflows | Author, refine, validate, apply, archive and recover ProductShape product meaning in a separate Spec Kit lane. | `process` | Read+Write | [productshape](https://github.com/juangcarmona/productshape) |
|
|
122
123
|
| Project Health Check | Diagnose a Spec Kit project and report health issues across structure, agents, features, scripts, extensions, and git | `visibility` | Read-only | [spec-kit-doctor](https://github.com/KhawarHabibKhan/spec-kit-doctor) |
|
|
123
124
|
| Project Status | Show current SDD workflow progress — active feature, artifact status, task completion, workflow phase, and extensions summary | `visibility` | Read-only | [spec-kit-status](https://github.com/KhawarHabibKhan/spec-kit-status) |
|
|
124
125
|
| QA Testing Extension | Systematic QA testing with browser-driven or CLI-based validation of acceptance criteria from spec | `code` | Read-only | [spec-kit-qa](https://github.com/arunt14/spec-kit-qa) |
|
|
@@ -147,7 +148,7 @@ The following community-contributed extensions are available in [`catalog.commun
|
|
|
147
148
|
| Spec Kit Figma | Grounds SpecKit spec/plan/tasks in Figma design context via REST or MCP, on macOS/Linux/Windows. | `integration` | Read+Write | [spec-kit-figma](https://github.com/Fyloss/spec-kit-figma) |
|
|
148
149
|
| Spec Kit Memory | Recalls prior specs and decisions from configurable memory tools (e.g. memsearch) before SDLC stages, so planning and specification start from what the project already knows | `docs` | Read+Write | [spec-kit-memory](https://github.com/zaytsevand/spec-kit-memory) |
|
|
149
150
|
| Spec Kit Preview | Generate evidence-backed low, mid, or high fidelity previews from Spec Kit artifacts as Markdown or self-contained HTML | `docs` | Read+Write | [spec-kit-preview](https://github.com/bigsmartben/spec-kit-preview) |
|
|
150
|
-
| Spec Kit Schedule |
|
|
151
|
+
| Spec Kit Schedule — parallel subagent rounds | Zero-config planner that turns tasks.md into optimal parallel rounds for subagents (CP-SAT, critical-path aware, file-conflict safe) and an implement command that runs them round by round with tasks.md checkboxes as the single source of progress. | `process` | Read+Write | [spec-kit-schedule](https://github.com/jfranc38/spec-kit-schedule) |
|
|
151
152
|
| Spec Kit TLDR | Render a feature's spec.md / plan.md into a review-oriented TLDR (self-contained HTML dashboard + PR-native Markdown) that surfaces risks for faster PR review. | `visibility` | Read+Write | [speckit-tldr](https://github.com/qurore/speckit-tldr) |
|
|
152
153
|
| Spec Orchestrator | Cross-feature orchestration — track state, select tasks, and detect conflicts across parallel specs | `process` | Read-only | [spec-kit-orchestrator](https://github.com/Quratulain-bilal/spec-kit-orchestrator) |
|
|
153
154
|
| Spec Reference Loader | Reads the ## References section from the feature spec and loads only the listed docs into context | `docs` | Read-only | [spec-kit-spec-reference-loader](https://github.com/KevinBrown5280/spec-kit-spec-reference-loader) |
|
|
@@ -53,7 +53,7 @@ specify init my-project --integration copilot --preset compliance
|
|
|
53
53
|
| `SPECKIT_INTEGRATION_DEFAULT` | Override the fallback integration used by `specify init` when `--integration` is omitted (interactive prompt default and non-interactive fallback). Set it to any registered integration key (e.g. `gemini`, `claude`). An unrecognized value is ignored with a warning and the built-in default (`copilot`) is used. An explicit `--integration <key>` always takes precedence. |
|
|
54
54
|
| `SPECIFY_INIT_DIR` | Target a member project from outside its directory (e.g. a monorepo root) without `cd`, for non-interactive / CI use. Set it to the **project root** — the directory *containing* `.specify/` (relative paths resolve against the current directory). The path must exist and contain `.specify/`, otherwise the command errors and does **not** fall back to the current directory. Resolved once in the core root helper (`get_repo_root` in Bash, `Get-RepoRoot` in PowerShell), so it is honored by the core feature scripts (`/speckit.plan`, `/speckit.tasks`, …) and the Git extension's feature-branch creation, which inherit it. The `specify` CLI applies the **same** validation rules to every project-scoped subcommand (`specify integration …`, `specify extension …`, `specify workflow …`, `specify preset …`, and the rest that operate on a `.specify/` project), so those can target a member project too. When unset, Bash/PowerShell helpers keep their existing upward search; the `specify` CLI keeps its project-scoped resolver cwd-only unless a command explicitly defines broader detection (for example, bundle commands). |
|
|
55
55
|
| `SPECIFY_FEATURE_DIRECTORY` | Override the active feature directory *within* the resolved project (takes precedence over `.specify/feature.json`). Relative paths resolve under the project root. Combine with `SPECIFY_INIT_DIR` to pick both the project and the feature non-interactively. |
|
|
56
|
-
| `SPECIFY_FEATURE` |
|
|
56
|
+
| `SPECIFY_FEATURE` | Explicitly override the active feature **label** (e.g. `001-photo-albums`) — the identifier the core helpers report as the current feature/branch (`get_current_branch` in Bash, `Get-CurrentBranch` in PowerShell). Those helpers never inspect Git: when the variable is set they return it verbatim, and when it is unset they return an empty string. The basename fallback happens later — `get_feature_paths` / `Get-FeaturePathsEnv` substitute the resolved feature directory's basename so the reported label is still usable — so calling the named helpers directly does **not** give you that fallback. You set it yourself: the Bash and Python feature scripts only **print** a commented `export SPECIFY_FEATURE=…` / `$env:SPECIFY_FEATURE = …` hint for you to run, because a child process cannot change its parent's environment, and `/speckit.specify` persists `feature_directory` to `.specify/feature.json` instead of setting this variable. (The PowerShell feature scripts do assign `$env:SPECIFY_FEATURE`, but that only reaches you when the script runs inside your current PowerShell session.) It does **not** locate the feature directory: with only `SPECIFY_FEATURE` set, `get_feature_paths` fails with *"Feature directory not found. Set `SPECIFY_FEATURE_DIRECTORY` or run the specify command to create `.specify/feature.json`."* Use `SPECIFY_FEATURE_DIRECTORY` (above) or `.specify/feature.json` to select the directory. |
|
|
57
57
|
|
|
58
58
|
> **Two resolution axes.** `SPECIFY_INIT_DIR` selects the **project** (which directory contains `.specify/`); `SPECIFY_FEATURE_DIRECTORY` / `.specify/feature.json` select the **feature** within that project. They are independent — project first, then feature.
|
|
59
59
|
|
|
@@ -540,6 +540,44 @@ specify workflow run speckit -i spec="Build a kanban board with drag-and-drop ta
|
|
|
540
540
|
|
|
541
541
|
> **Security note:** a `shell` step runs a local command with **your** privileges. There is no capability sandbox — `requires` is an advisory pre-condition block (spec-kit version, integrations), not a runtime gate, so it does **not** restrict what a step can do. In particular there is no `requires.permissions` capability gate: it is rejected by validation precisely because it would imply a sandbox that does not exist. Review any catalog or downloaded workflow before running it, and use a `gate` step to require explicit approval before sensitive or destructive shell commands.
|
|
542
542
|
|
|
543
|
+
### Per-Step Integration Configuration
|
|
544
|
+
|
|
545
|
+
Command steps may pass structured runtime configuration to integrations that
|
|
546
|
+
support it:
|
|
547
|
+
|
|
548
|
+
```yaml
|
|
549
|
+
- id: implement-with-docker-agent
|
|
550
|
+
type: command
|
|
551
|
+
command: speckit.implement
|
|
552
|
+
integration: docker-agent
|
|
553
|
+
integration_args:
|
|
554
|
+
- "{{ inputs.agent_config }}"
|
|
555
|
+
integration_options:
|
|
556
|
+
agent: root
|
|
557
|
+
safety: balanced
|
|
558
|
+
model: "openai/gpt-5"
|
|
559
|
+
input:
|
|
560
|
+
args: "{{ inputs.spec }}"
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
`integration_args` is an ordered list of strings. `integration_options` is a
|
|
564
|
+
mapping with string keys. Values in both fields are resolved with the workflow
|
|
565
|
+
expression mechanism and validated by the selected integration; unsupported,
|
|
566
|
+
unknown, or malformed values fail with an actionable error. Docker Agent uses
|
|
567
|
+
its single positional argument as the agent configuration reference and accepts
|
|
568
|
+
`agent` and `safety` as named integration options. Configure its model through
|
|
569
|
+
the command step's top-level `model` field.
|
|
570
|
+
|
|
571
|
+
When Docker Agent `integration_args` supplies an agent reference for a command
|
|
572
|
+
step, it takes precedence over `SPECKIT_INTEGRATION_DOCKER_AGENT_EXTRA_ARGS`;
|
|
573
|
+
the entire legacy environment value is ignored for that step. Without a per-step
|
|
574
|
+
agent reference, the legacy environment behavior is unchanged.
|
|
575
|
+
|
|
576
|
+
Resolved runtime configuration is recorded in workflow run state. When a failed
|
|
577
|
+
or paused command is resumed, the complete dispatch configuration is re-resolved
|
|
578
|
+
from the current inputs, so values supplied with `workflow resume --input` take
|
|
579
|
+
effect consistently. A resume without updated inputs reproduces the same values.
|
|
580
|
+
|
|
543
581
|
## Expressions
|
|
544
582
|
|
|
545
583
|
Steps can reference inputs and previous step outputs using `{{ expression }}` syntax:
|
|
@@ -625,6 +625,13 @@ See the [Extension Publishing Guide](EXTENSION-PUBLISHING-GUIDE.md) for detailed
|
|
|
625
625
|
- **MAJOR**: Breaking changes
|
|
626
626
|
- **MINOR**: New features
|
|
627
627
|
- **PATCH**: Bug fixes
|
|
628
|
+
- **Bump on every content change**: update offers from `specify extension
|
|
629
|
+
update` are version-driven, so a content change shipped without a
|
|
630
|
+
version bump is never delivered automatically to already-installed
|
|
631
|
+
copies. For the bundled extensions in this repository the bump is
|
|
632
|
+
enforced by CI (`extension-version-guard.yml`): a PR that changes
|
|
633
|
+
files under `extensions/<id>/` must also bump that extension's
|
|
634
|
+
`extension.yml` version and keep `extensions/catalog.json` in sync.
|
|
628
635
|
|
|
629
636
|
### Security
|
|
630
637
|
|
|
@@ -26,7 +26,8 @@ flowchart LR
|
|
|
26
26
|
A[intake] --> R[research] --> D[define] --> S[shape] --> C{decide}
|
|
27
27
|
C -->|go| SPEC[/speckit.specify/]
|
|
28
28
|
C -->|kill| X[closed, recorded]
|
|
29
|
-
C -.->|needs-clarification
|
|
29
|
+
C -.->|needs-clarification| F[refine named artifact in place]
|
|
30
|
+
F -.->|then revise decision.md| C
|
|
30
31
|
```
|
|
31
32
|
|
|
32
33
|
## Commands
|
|
@@ -45,6 +46,27 @@ Stages are meant to run in order but are not rigidly gated:
|
|
|
45
46
|
- `shape` requires `problem.md`.
|
|
46
47
|
- `decide` requires `problem.md`; a `go` verdict expects `concept.md` (otherwise it is downgraded to `needs-clarification`).
|
|
47
48
|
|
|
49
|
+
## Resolving clarifications
|
|
50
|
+
|
|
51
|
+
The normal process is sequential and each command usually runs **once**:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
intake → research → define → shape → decide
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Each stage writes a Markdown artifact under `.specify/assessments/<slug>/`. Those files stay editable. The commands keep their existing output templates: they do not rewrite an earlier artifact or perform that refinement themselves. `[NEEDS CLARIFICATION: …]` markers are gaps in the artifact, not a signal to regenerate the whole stage from scratch.
|
|
58
|
+
|
|
59
|
+
Resolve them by refining the existing file:
|
|
60
|
+
|
|
61
|
+
1. **Edit the Markdown directly** (fill in the missing metric, owner, constraint, and so on), or
|
|
62
|
+
2. **Ask the agent in free-form chat** to incorporate the missing information into that artifact.
|
|
63
|
+
|
|
64
|
+
Then ask whether the new information clears the blocker and to update any downstream wording that depended on it. That includes `decision.md`: you can supply the missing facts and ask the agent to revise the scorecard, rationale, verdict, or handoff. That is artifact refinement, not command iteration.
|
|
65
|
+
|
|
66
|
+
When you add evidence, keep the source and confidence tags the research stage already uses (`ASSUMPTION` vs cited claims). Do not invent citations.
|
|
67
|
+
|
|
68
|
+
Rerunning an earlier `speckit.assess.*` command is the exception (for example after a wrong slug or a discarded draft), not the default path for answering clarification markers.
|
|
69
|
+
|
|
48
70
|
## Slug Conventions
|
|
49
71
|
|
|
50
72
|
A *slug* is the per-idea directory name under `.specify/assessments/`. It is the handle all five commands share.
|