specify-cli 0.12.11__tar.gz → 0.12.13__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-0.12.11 → specify_cli-0.12.13}/CHANGELOG.md +30 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/PKG-INFO +2 -2
- {specify_cli-0.12.11 → specify_cli-0.12.13}/README.md +1 -1
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/community/extensions.md +1 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/install/one-time.md +2 -1
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/install/pipx.md +2 -1
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/installation.md +1 -1
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/reference/bundles.md +5 -4
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/reference/integrations.md +2 -1
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/catalog.community.json +35 -1
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/ARCHITECTURE.md +1 -2
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/self-test/preset.yml +0 -6
- {specify_cli-0.12.11 → specify_cli-0.12.13}/pyproject.toml +1 -1
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/agents.py +49 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/commands/bundle/__init__.py +37 -23
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/extensions/__init__.py +25 -6
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/extensions/_commands.py +8 -1
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/kiro_cli/__init__.py +1 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/presets/__init__.py +40 -2
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/presets/_commands.py +8 -1
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/catalog.py +13 -5
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/engine.py +10 -1
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/expressions.py +22 -2
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/steps/if_then/__init__.py +2 -2
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/steps/shell/__init__.py +43 -20
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/steps/switch/__init__.py +14 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/templates/commands/constitution.md +1 -1
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/contract/test_bundle_cli.py +29 -7
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integration/test_bundler_local_install.py +59 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_kiro_cli.py +3 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_extension_skills.py +59 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_extensions.py +268 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_presets.py +368 -1
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_workflows.py +318 -101
- {specify_cli-0.12.11 → specify_cli-0.12.13}/workflows/README.md +6 -0
- specify_cli-0.12.11/presets/self-test/templates/agent-file-template.md +0 -9
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.devcontainer/devcontainer.json +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.devcontainer/post-create.sh +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.editorconfig +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.gitattributes +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/CODEOWNERS +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/ISSUE_TEMPLATE/agent_request.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/ISSUE_TEMPLATE/bundle_submission.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/ISSUE_TEMPLATE/extension_submission.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/ISSUE_TEMPLATE/preset_submission.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/aw/actions-lock.json +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/dependabot.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/skills/add-community-extension/SKILL.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/RELEASE-PROCESS.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/add-community-extension.lock.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/add-community-extension.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/add-community-preset.lock.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/add-community-preset.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/bug-assess.lock.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/bug-assess.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/bug-fix.lock.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/bug-fix.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/bug-test.lock.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/bug-test.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/catalog-assign.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/codeql.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/docs.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/lint.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/publish-pypi.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/release-trigger.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/release.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/stale.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.github/workflows/test.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.gitignore +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.markdownlint-cli2.jsonc +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.pre-commit-config.yaml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/.zenodo.json +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/AGENTS.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/CITATION.cff +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/CODE_OF_CONDUCT.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/CONTRIBUTING.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/DEVELOPMENT.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/LICENSE +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/SECURITY.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/SUPPORT.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/.gitignore +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/README.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/community/bundles.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/community/friends.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/community/overview.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/community/presets.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/community/walkthroughs.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/concepts/complex-features.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/concepts/sdd.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/concepts/spec-persistence.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/docfx.json +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/guides/evolving-specs.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/guides/monorepo.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/index.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/install/air-gapped.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/install/uv.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/local-development.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/quickstart.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/reference/authentication.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/reference/core.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/reference/extensions.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/reference/overview.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/reference/presets.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/reference/workflows.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/template/public/main.css +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/toc.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/docs/upgrade.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/examples/bundles/business-analyst/README.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/examples/bundles/business-analyst/bundle.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/examples/bundles/developer/README.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/examples/bundles/developer/bundle.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/examples/bundles/product-manager/README.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/examples/bundles/product-manager/bundle.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/examples/bundles/security-researcher/README.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/examples/bundles/security-researcher/bundle.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/EXTENSION-API-REFERENCE.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/EXTENSION-DEVELOPMENT-GUIDE.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/EXTENSION-PUBLISHING-GUIDE.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/EXTENSION-USER-GUIDE.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/README.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/RFC-EXTENSION-SYSTEM.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/agent-context/README.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/agent-context/agent-context-config.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/agent-context/agent-context-defaults.json +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/agent-context/commands/speckit.agent-context.update.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/agent-context/extension.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/agent-context/scripts/bash/update-agent-context.sh +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/agent-context/scripts/powershell/update-agent-context.ps1 +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/agent-context/scripts/python/update_agent_context.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/bug/README.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/bug/commands/speckit.bug.assess.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/bug/commands/speckit.bug.fix.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/bug/commands/speckit.bug.test.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/bug/extension.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/catalog.json +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/README.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/commands/speckit.git.commit.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/commands/speckit.git.feature.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/commands/speckit.git.initialize.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/commands/speckit.git.remote.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/commands/speckit.git.validate.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/config-template.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/extension.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/git-config.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/scripts/bash/auto-commit.sh +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/scripts/bash/create-new-feature-branch.sh +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/scripts/bash/git-common.sh +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/scripts/bash/initialize-repo.sh +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/scripts/powershell/auto-commit.ps1 +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/scripts/powershell/create-new-feature-branch.ps1 +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/scripts/powershell/git-common.ps1 +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/git/scripts/powershell/initialize-repo.ps1 +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/selftest/commands/selftest.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/selftest/extension.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/template/.gitignore +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/template/CHANGELOG.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/template/EXAMPLE-README.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/template/LICENSE +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/template/README.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/template/commands/example.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/template/config-template.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/extensions/template/extension.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/integrations/CONTRIBUTING.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/integrations/README.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/integrations/catalog.community.json +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/integrations/catalog.json +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/media/bootstrap-claude-code.gif +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/media/logo_large.webp +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/media/logo_small.webp +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/media/spec-kit-video-header.jpg +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/media/specify_cli.gif +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/newsletters/2026-April.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/newsletters/2026-February.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/newsletters/2026-June.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/newsletters/2026-March.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/newsletters/2026-May.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/PUBLISHING.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/README.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/catalog.community.json +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/catalog.json +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/lean/README.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/lean/commands/speckit.constitution.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/lean/commands/speckit.implement.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/lean/commands/speckit.plan.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/lean/commands/speckit.specify.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/lean/commands/speckit.tasks.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/lean/preset.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/scaffold/README.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/scaffold/commands/speckit.myext.myextcmd.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/scaffold/commands/speckit.specify.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/scaffold/preset.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/scaffold/templates/myext-template.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/scaffold/templates/spec-template.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/self-test/commands/speckit.specify.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/self-test/commands/speckit.wrap-test.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/self-test/templates/checklist-template.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/self-test/templates/constitution-template.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/self-test/templates/plan-template.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/self-test/templates/spec-template.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/presets/self-test/templates/tasks-template.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/scripts/bash/check-prerequisites.sh +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/scripts/bash/common.sh +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/scripts/bash/create-new-feature.sh +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/scripts/bash/setup-plan.sh +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/scripts/bash/setup-tasks.sh +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/scripts/powershell/check-prerequisites.ps1 +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/scripts/powershell/common.ps1 +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/scripts/powershell/create-new-feature.ps1 +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/scripts/powershell/setup-plan.ps1 +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/scripts/powershell/setup-tasks.ps1 +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/scripts/python/check_prerequisites.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/scripts/python/common.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/spec-driven.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/spec-kit.code-workspace +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/_agent_config.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/_assets.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/_console.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/_github_http.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/_init_options.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/_invocation_style.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/_project.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/_toml_string.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/_utils.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/_version.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/authentication/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/authentication/azure_devops.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/authentication/base.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/authentication/config.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/authentication/github.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/authentication/http.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/commands_impl/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/commands_impl/catalog_config.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/lib/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/lib/project.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/lib/versioning.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/lib/yamlio.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/models/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/models/catalog.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/models/manifest.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/models/records.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/services/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/services/adapters.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/services/catalog_stack.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/services/conflict.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/services/installer.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/services/packager.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/services/primitives.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/services/references.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/services/resolver.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/bundler/services/validator.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/catalogs.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/commands/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/commands/init.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integration_runtime.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integration_scaffold.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integration_state.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integration_status.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/_commands.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/_helpers.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/_install_commands.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/_migrate_commands.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/_query_commands.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/_scaffold_commands.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/agy/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/amp/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/auggie/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/base.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/bob/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/catalog.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/claude/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/cline/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/codebuddy/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/codex/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/copilot/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/cursor_agent/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/devin/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/firebender/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/forge/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/gemini/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/generic/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/goose/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/hermes/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/junie/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/kilocode/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/kimi/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/lingma/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/manifest.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/omp/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/opencode/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/pi/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/qodercli/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/qwen/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/rovodev/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/shai/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/tabnine/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/trae/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/vibe/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/zcode/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/integrations/zed/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/shared_infra.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/_commands.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/base.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/steps/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/steps/command/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/steps/do_while/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/steps/fan_in/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/steps/fan_out/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/steps/gate/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/steps/init/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/steps/prompt/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/src/specify_cli/workflows/steps/while_loop/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/templates/checklist-template.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/templates/commands/analyze.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/templates/commands/checklist.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/templates/commands/clarify.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/templates/commands/converge.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/templates/commands/implement.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/templates/commands/plan.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/templates/commands/specify.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/templates/commands/tasks.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/templates/commands/taskstoissues.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/templates/constitution-template.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/templates/plan-template.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/templates/spec-template.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/templates/tasks-template.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/templates/vscode-settings.json +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/auth_helpers.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/bundler_helpers.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/conftest.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/contract/test_catalog_schema.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/contract/test_manifest_schema.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/extensions/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/extensions/bug/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/extensions/bug/test_bug_extension.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/extensions/git/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/extensions/git/test_git_extension.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/extensions/test_agent_context_cli_free.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/extensions/test_extension_agent_context.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/extensions/test_update_agent_context_feature_json.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/extensions/test_update_agent_context_python_parity.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/hooks/TESTING.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/hooks/plan.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/hooks/spec.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/hooks/tasks.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/http_helpers.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integration/test_bundler_catalog_stack.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integration/test_bundler_init_install.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integration/test_bundler_install_flow.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integration/test_bundler_offline.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integration/test_bundler_security_paths.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/__init__.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/conftest.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_base.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_cli.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_extra_args.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_home_isolation.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_agy.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_amp.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_auggie.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_base_markdown.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_base_skills.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_base_toml.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_base_yaml.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_bob.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_catalog.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_claude.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_cline.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_codebuddy.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_codex.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_copilot.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_cursor_agent.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_devin.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_firebender.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_forge.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_gemini.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_generic.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_goose.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_hermes.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_junie.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_kilocode.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_kimi.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_lingma.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_omp.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_opencode.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_pi.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_qodercli.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_qwen.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_rovodev.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_scaffold.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_shai.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_state.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_subcommand.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_tabnine.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_trae.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_vibe.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_zcode.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_integration_zed.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_manifest.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_registry.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/integrations/test_skill_frontmatter_quoting.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/self_upgrade_helpers.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_agent_config_consistency.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_authentication.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_branch_numbering.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_check_prerequisites_paths_only.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_check_prerequisites_python_parity.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_check_tool.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_cli_version.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_command_template_py_scripts.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_commands_package.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_console_imports.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_extension_registration.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_extension_update_hardening.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_github_http.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_github_workflows.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_init_dir.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_init_dir_cli.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_live_transient_windows.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_merge.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_post_process.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_ps1_encoding.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_registrar_path_traversal.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_self_upgrade_detection.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_self_upgrade_execution.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_self_upgrade_guidance.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_self_upgrade_verification.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_setup_plan_feature_json.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_setup_plan_no_overwrite.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_setup_tasks.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_shared_infra_integrity.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_timestamp_branches.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_upgrade.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_utils.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_utils_assets_imports.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_version_imports.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/test_workflow_run_without_project.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/unit/test_bundler_adapters.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/unit/test_bundler_catalog_config.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/unit/test_bundler_conflict.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/unit/test_bundler_packager.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/unit/test_bundler_primitives.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/unit/test_bundler_records.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/unit/test_bundler_references.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/unit/test_bundler_resolver.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/unit/test_bundler_validator.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/tests/unit/test_bundler_versioning.py +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/workflows/ARCHITECTURE.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/workflows/PUBLISHING.md +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/workflows/catalog.community.json +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/workflows/catalog.json +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/workflows/speckit/workflow.yml +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/workflows/step-catalog.community.json +0 -0
- {specify_cli-0.12.11 → specify_cli-0.12.13}/workflows/step-catalog.json +0 -0
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- insert new changelog below this comment -->
|
|
4
4
|
|
|
5
|
+
## [0.12.13] - 2026-07-13
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- fix(workflows): fail switch step on non-mapping cases instead of crashing (#3481)
|
|
10
|
+
- Cleanup agent-file-template.md (#2579)
|
|
11
|
+
- fix: mark Kiro integration as multi-install safe (#3472)
|
|
12
|
+
- fix: rewrite extension-relative subdir paths in generated command bodies (#3444)
|
|
13
|
+
- fix(templates): point constitution sync checklist at installed command files (#3418)
|
|
14
|
+
- feat(workflows): make shell step timeout configurable (#3327) (#3328)
|
|
15
|
+
- docs: clarify that release tags keep the leading v prefix (#3463)
|
|
16
|
+
- fix(workflows): don't crash on membership test against a non-iterable (#3448)
|
|
17
|
+
- fix(workflows): if-step validate accepts falsy non-list else (#3264)
|
|
18
|
+
- chore: release 0.12.12, begin 0.12.13.dev0 development (#3490)
|
|
19
|
+
|
|
20
|
+
## [0.12.12] - 2026-07-13
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- fix(extensions): set-priority repairs corrupted boolean priority (#3268)
|
|
25
|
+
- fix(presets): set-priority repairs corrupted boolean priority (#3269)
|
|
26
|
+
- fix(workflows): engine loop cap ignores bool max_iterations (#3270)
|
|
27
|
+
- docs(bundles): document --integration on 'bundle update' (#3271)
|
|
28
|
+
- fix(workflows): harden catalog.py against mis-shaped registry & non-string fields (#3375)
|
|
29
|
+
- Add Verify Review Ship extension to community catalog (#3450)
|
|
30
|
+
- fix(bundle): reject file:// / local download_url — catalog URLs are HTTPS-only (#3344)
|
|
31
|
+
- fix(extensions): handle prefix-colliding env vars in _get_env_config (#3350)
|
|
32
|
+
- docs: document copilot skills mode (--skills) and markdown deprecation (#3313)
|
|
33
|
+
- chore: release 0.12.11, begin 0.12.12.dev0 development (#3460)
|
|
34
|
+
|
|
5
35
|
## [0.12.11] - 2026-07-10
|
|
6
36
|
|
|
7
37
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: specify-cli
|
|
3
|
-
Version: 0.12.
|
|
3
|
+
Version: 0.12.13
|
|
4
4
|
Summary: Specify CLI, part of GitHub Spec Kit. A tool to bootstrap your projects for Spec-Driven Development (SDD).
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -65,7 +65,7 @@ Spec-Driven Development **flips the script** on traditional software development
|
|
|
65
65
|
|
|
66
66
|
### 1. Install Specify CLI
|
|
67
67
|
|
|
68
|
-
Requires **[uv](https://docs.astral.sh/uv/)** ([install uv](./docs/install/uv.md)). Replace `vX.Y.Z` with the latest tag from [Releases](https://github.com/github/spec-kit/releases):
|
|
68
|
+
Requires **[uv](https://docs.astral.sh/uv/)** ([install uv](./docs/install/uv.md)). Replace `vX.Y.Z` with the latest release tag from [Releases](https://github.com/github/spec-kit/releases) — keep the leading `v` (for example, `v0.12.11`, not `0.12.11`):
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
71
|
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git@vX.Y.Z
|
|
@@ -45,7 +45,7 @@ Spec-Driven Development **flips the script** on traditional software development
|
|
|
45
45
|
|
|
46
46
|
### 1. Install Specify CLI
|
|
47
47
|
|
|
48
|
-
Requires **[uv](https://docs.astral.sh/uv/)** ([install uv](./docs/install/uv.md)). Replace `vX.Y.Z` with the latest tag from [Releases](https://github.com/github/spec-kit/releases):
|
|
48
|
+
Requires **[uv](https://docs.astral.sh/uv/)** ([install uv](./docs/install/uv.md)). Replace `vX.Y.Z` with the latest release tag from [Releases](https://github.com/github/spec-kit/releases) — keep the leading `v` (for example, `v0.12.11`, not `0.12.11`):
|
|
49
49
|
|
|
50
50
|
```bash
|
|
51
51
|
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git@vX.Y.Z
|
|
@@ -148,6 +148,7 @@ The following community-contributed extensions are available in [`catalog.commun
|
|
|
148
148
|
| Token Economy | Token routing, measured savings, and context audit workflows | `process` | Read+Write | [spec-kit-token-economy](https://github.com/formin/spec-kit-token-economy) |
|
|
149
149
|
| V-Model Extension Pack | Enforces V-Model paired generation of development specs and test specs with full traceability | `docs` | Read+Write | [spec-kit-v-model](https://github.com/leocamello/spec-kit-v-model) |
|
|
150
150
|
| Verify Extension | Post-implementation quality gate that validates implemented code against specification artifacts | `code` | Read-only | [spec-kit-verify](https://github.com/ismaelJimenez/spec-kit-verify) |
|
|
151
|
+
| Verify Review Ship | Adds post-implementation verify, review, and ship readiness gates to Spec Kit workflows | `process` | Read-only | [spec-kit-verify-review-ship](https://github.com/cadugevaerd/spec-kit-verify-review-ship) |
|
|
151
152
|
| Verify Tasks Extension | Detect phantom completions: tasks marked [X] in tasks.md with no real implementation | `code` | Read-only | [spec-kit-verify-tasks](https://github.com/datastone-inc/spec-kit-verify-tasks) |
|
|
152
153
|
| Version Guard | Verify tech stack versions against live npm registries before planning and implementation | `process` | Read-only | [spec-kit-version-guard](https://github.com/KevinBrown5280/spec-kit-version-guard) |
|
|
153
154
|
| What-if Analysis | Preview the downstream impact (complexity, effort, tasks, risks) of requirement changes before committing to them | `visibility` | Read-only | [spec-kit-whatif](https://github.com/DevAbdullah90/spec-kit-whatif) |
|
|
@@ -11,7 +11,8 @@ If you want to try Spec Kit without installing it permanently, use `uvx` to run
|
|
|
11
11
|
# Create a new project (latest from main)
|
|
12
12
|
uvx --from git+https://github.com/github/spec-kit.git specify init <PROJECT_NAME>
|
|
13
13
|
|
|
14
|
-
# Or target a specific release (replace vX.Y.Z with a tag from Releases
|
|
14
|
+
# Or target a specific release (replace vX.Y.Z with a tag from Releases;
|
|
15
|
+
# keep the leading v, e.g. v0.12.11 not 0.12.11)
|
|
15
16
|
uvx --from git+https://github.com/github/spec-kit.git@vX.Y.Z specify init <PROJECT_NAME>
|
|
16
17
|
|
|
17
18
|
# Initialize in the current directory
|
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
Pin a specific release tag for stability (check [Releases](https://github.com/github/spec-kit/releases) for the latest):
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
# Install a specific stable release (recommended — replace vX.Y.Z with the
|
|
10
|
+
# Install a specific stable release (recommended — replace vX.Y.Z with the
|
|
11
|
+
# latest tag, keeping the leading v, e.g. v0.12.11 not 0.12.11)
|
|
11
12
|
pipx install git+https://github.com/github/spec-kit.git@vX.Y.Z
|
|
12
13
|
|
|
13
14
|
# Or install latest from main (may include unreleased changes)
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
### Persistent Installation (Recommended)
|
|
17
17
|
|
|
18
|
-
Install once and use everywhere. Replace `vX.Y.Z` with a tag from [Releases](https://github.com/github/spec-kit/releases):
|
|
18
|
+
Install once and use everywhere. Replace `vX.Y.Z` with a release tag from [Releases](https://github.com/github/spec-kit/releases) — keep the leading `v` (for example, `v0.12.11`, not `0.12.11`):
|
|
19
19
|
|
|
20
20
|
> [!NOTE]
|
|
21
21
|
> The command below requires **[uv](https://docs.astral.sh/uv/)**. If you see `command not found: uv`, [install uv first](./install/uv.md).
|
|
@@ -51,10 +51,11 @@ If the current directory is not yet a Spec Kit project, `install` initializes on
|
|
|
51
51
|
specify bundle update [<bundle_id>]
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
| Option
|
|
55
|
-
|
|
|
56
|
-
| `--all`
|
|
57
|
-
| `--
|
|
54
|
+
| Option | Description |
|
|
55
|
+
| ---------------- | --------------------------------------------------------------------------------------------------------------------- |
|
|
56
|
+
| `--all` | Update every installed bundle |
|
|
57
|
+
| `--integration` | Override the integration used when refreshing components; applied only when the project's active integration can't be determined |
|
|
58
|
+
| `--offline` | Do not access the network |
|
|
58
59
|
|
|
59
60
|
Re-resolves a bundle and **refreshes** its components through each primitive's update path, bringing already-installed components up to the bundle's newly pinned versions while preserving primitive-level overrides (such as preset priority). Provide a bundle id, or use `--all` to update everything installed.
|
|
60
61
|
|
|
@@ -18,7 +18,7 @@ The Specify CLI supports a wide range of AI coding agents. When you run `specify
|
|
|
18
18
|
| [Firebender](https://firebender.com/) | `firebender` | IDE-based agent for Android Studio / IntelliJ |
|
|
19
19
|
| [Forge](https://forgecode.dev/) | `forge` | |
|
|
20
20
|
| [Gemini CLI](https://github.com/google-gemini/gemini-cli) | `gemini` | |
|
|
21
|
-
| [GitHub Copilot](https://code.visualstudio.com/) | `copilot` |
|
|
21
|
+
| [GitHub Copilot](https://code.visualstudio.com/) | `copilot` | Defaults to legacy markdown mode: `.agent.md` command files under `.github/agents/`, companion `.prompt.md` files under `.github/prompts/`, and a `.vscode/settings.json` merge. Pass `--integration-options="--skills"` to scaffold skills as `speckit-<command>/SKILL.md` under `.github/skills/` instead. Legacy markdown mode is deprecated and will stop being the default in a future release. |
|
|
22
22
|
| [Goose](https://goose-docs.ai/) | `goose` | Uses YAML recipe format in `.goose/recipes/` |
|
|
23
23
|
| [Hermes](https://github.com/NousResearch/hermes-agent) | `hermes` | Skills-based integration; installs skills globally into `~/.hermes/skills/` |
|
|
24
24
|
| [IBM Bob](https://www.ibm.com/products/bob) | `bob` | IDE-based agent |
|
|
@@ -219,6 +219,7 @@ Some integrations accept additional options via `--integration-options`:
|
|
|
219
219
|
| ----------- | ------------------- | -------------------------------------------------------------- |
|
|
220
220
|
| `generic` | `--commands-dir` | Required. Directory for command files |
|
|
221
221
|
| `kimi` | `--migrate-legacy` | Migrate legacy `.kimi/skills/` installs to `.kimi-code/skills/` (including dotted→hyphenated skill naming, e.g. `speckit.xxx` → `speckit-xxx`) |
|
|
222
|
+
| `copilot` | `--skills` | Scaffold commands as agent skills (`speckit-<command>/SKILL.md` under `.github/skills/`, invoked as `/speckit-<command>`) instead of the default legacy markdown mode (`.github/agents/*.agent.md` plus `.github/prompts/*.prompt.md` and a `.vscode/settings.json` merge). Without this flag, install warns that legacy markdown mode is deprecated. |
|
|
222
223
|
|
|
223
224
|
Example:
|
|
224
225
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": "1.0",
|
|
3
|
-
"updated_at": "2026-07-
|
|
3
|
+
"updated_at": "2026-07-10T00:00:00Z",
|
|
4
4
|
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.community.json",
|
|
5
5
|
"extensions": {
|
|
6
6
|
"aide": {
|
|
@@ -4356,6 +4356,40 @@
|
|
|
4356
4356
|
"created_at": "2026-03-03T00:00:00Z",
|
|
4357
4357
|
"updated_at": "2026-04-09T00:00:00Z"
|
|
4358
4358
|
},
|
|
4359
|
+
"verify-review-ship": {
|
|
4360
|
+
"name": "Verify Review Ship",
|
|
4361
|
+
"id": "verify-review-ship",
|
|
4362
|
+
"description": "Adds post-implementation verify, review, and ship readiness gates to Spec Kit workflows.",
|
|
4363
|
+
"author": "Carlos Eduardo Gevaerd Araujo",
|
|
4364
|
+
"version": "0.1.0",
|
|
4365
|
+
"download_url": "https://github.com/cadugevaerd/spec-kit-verify-review-ship/archive/refs/tags/v0.1.0.zip",
|
|
4366
|
+
"repository": "https://github.com/cadugevaerd/spec-kit-verify-review-ship",
|
|
4367
|
+
"homepage": "https://github.com/cadugevaerd/spec-kit-verify-review-ship",
|
|
4368
|
+
"documentation": "https://github.com/cadugevaerd/spec-kit-verify-review-ship/blob/main/README.md",
|
|
4369
|
+
"changelog": "https://github.com/cadugevaerd/spec-kit-verify-review-ship/blob/main/CHANGELOG.md",
|
|
4370
|
+
"license": "MIT",
|
|
4371
|
+
"category": "process",
|
|
4372
|
+
"effect": "read-only",
|
|
4373
|
+
"requires": {
|
|
4374
|
+
"speckit_version": ">=0.1.0"
|
|
4375
|
+
},
|
|
4376
|
+
"provides": {
|
|
4377
|
+
"commands": 3,
|
|
4378
|
+
"hooks": 1
|
|
4379
|
+
},
|
|
4380
|
+
"tags": [
|
|
4381
|
+
"quality",
|
|
4382
|
+
"review",
|
|
4383
|
+
"shipping",
|
|
4384
|
+
"workflow",
|
|
4385
|
+
"testing"
|
|
4386
|
+
],
|
|
4387
|
+
"verified": false,
|
|
4388
|
+
"downloads": 0,
|
|
4389
|
+
"stars": 0,
|
|
4390
|
+
"created_at": "2026-07-10T00:00:00Z",
|
|
4391
|
+
"updated_at": "2026-07-10T00:00:00Z"
|
|
4392
|
+
},
|
|
4359
4393
|
"verify-tasks": {
|
|
4360
4394
|
"name": "Verify Tasks Extension",
|
|
4361
4395
|
"id": "verify-tasks",
|
|
@@ -44,12 +44,6 @@ provides:
|
|
|
44
44
|
description: "Self-test constitution template"
|
|
45
45
|
replaces: "constitution-template"
|
|
46
46
|
|
|
47
|
-
- type: "template"
|
|
48
|
-
name: "agent-file-template"
|
|
49
|
-
file: "templates/agent-file-template.md"
|
|
50
|
-
description: "Self-test agent file template"
|
|
51
|
-
replaces: "agent-file-template"
|
|
52
|
-
|
|
53
47
|
- type: "command"
|
|
54
48
|
name: "speckit.specify"
|
|
55
49
|
file: "commands/speckit.specify.md"
|
|
@@ -213,6 +213,52 @@ class CommandRegistrar:
|
|
|
213
213
|
".specify.specify/", ".specify/"
|
|
214
214
|
)
|
|
215
215
|
|
|
216
|
+
@staticmethod
|
|
217
|
+
def rewrite_extension_paths(
|
|
218
|
+
text: str, extension_id: str, extension_dir: Path
|
|
219
|
+
) -> str:
|
|
220
|
+
"""Rewrite extension-relative paths to their installed locations.
|
|
221
|
+
|
|
222
|
+
Extension command bodies reference bundled files relative to the
|
|
223
|
+
extension root (e.g. ``agents/control/commander.md``). After install
|
|
224
|
+
those files live under ``.specify/extensions/<id>/``, so bare
|
|
225
|
+
references would resolve against the workspace root and never be
|
|
226
|
+
found (#2101).
|
|
227
|
+
|
|
228
|
+
Only directories that actually exist inside *extension_dir* are
|
|
229
|
+
rewritten, keeping the behaviour conservative and avoiding false
|
|
230
|
+
positives on prose. ``commands`` (slash-command sources), ``specs``
|
|
231
|
+
(user project artifacts) and dot-directories are never rewritten.
|
|
232
|
+
"""
|
|
233
|
+
if not isinstance(text, str) or not text:
|
|
234
|
+
return text
|
|
235
|
+
|
|
236
|
+
skip = {"commands", ".git", "specs"}
|
|
237
|
+
try:
|
|
238
|
+
subdirs = [
|
|
239
|
+
entry.name
|
|
240
|
+
for entry in extension_dir.iterdir()
|
|
241
|
+
if entry.is_dir()
|
|
242
|
+
and entry.name not in skip
|
|
243
|
+
and not entry.name.startswith(".")
|
|
244
|
+
]
|
|
245
|
+
except OSError:
|
|
246
|
+
return text
|
|
247
|
+
|
|
248
|
+
for subdir in subdirs:
|
|
249
|
+
# Only rewrite relative references (subdir/... or ./subdir/...);
|
|
250
|
+
# absolute paths like /subdir/... keep their meaning. Use a
|
|
251
|
+
# callable replacement: subdir/extension_id come from the
|
|
252
|
+
# filesystem and could contain backslashes or "\1"-like
|
|
253
|
+
# sequences, which would corrupt a string replacement template.
|
|
254
|
+
replacement = f".specify/extensions/{extension_id}/{subdir}/"
|
|
255
|
+
text = re.sub(
|
|
256
|
+
r'(^|[\s`"\'(])(?:\./)?' + re.escape(subdir) + "/",
|
|
257
|
+
lambda m: m.group(1) + replacement,
|
|
258
|
+
text,
|
|
259
|
+
)
|
|
260
|
+
return text
|
|
261
|
+
|
|
216
262
|
def render_markdown_command(
|
|
217
263
|
self, frontmatter: dict, body: str, source_id: str, context_note: str = None
|
|
218
264
|
) -> str:
|
|
@@ -639,6 +685,9 @@ class CommandRegistrar:
|
|
|
639
685
|
frontmatter[key] = core_frontmatter[key]
|
|
640
686
|
frontmatter.pop("strategy", None)
|
|
641
687
|
|
|
688
|
+
if extension_id:
|
|
689
|
+
body = self.rewrite_extension_paths(body, extension_id, source_root)
|
|
690
|
+
|
|
642
691
|
frontmatter = self._adjust_script_paths(
|
|
643
692
|
frontmatter, extension_id=extension_id
|
|
644
693
|
)
|
|
@@ -746,11 +746,16 @@ def _resolve_manifest_path(path: Path | None) -> Path:
|
|
|
746
746
|
def _download_manifest(resolved, *, offline: bool):
|
|
747
747
|
"""Resolve a bundle's manifest from its catalog ``download_url``.
|
|
748
748
|
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
749
|
+
Catalog ``download_url``s are HTTPS-only (``http`` allowed for localhost),
|
|
750
|
+
matching the extensions/presets/workflows catalog systems. Remote URLs are
|
|
751
|
+
fetched with the shared authenticated, redirect-validated HTTP client, and
|
|
752
|
+
only when not ``--offline``.
|
|
753
|
+
|
|
754
|
+
Local and ``file://`` sources are intentionally not resolved here: to
|
|
755
|
+
install a bundle from disk, pass the path positionally
|
|
756
|
+
(``specify bundle install ./path/to/bundle.yml`` — a bundle directory or a
|
|
757
|
+
``.zip`` artifact also works), which :func:`_local_manifest_source` handles
|
|
758
|
+
before catalog resolution and which never touches ``download_url``.
|
|
754
759
|
"""
|
|
755
760
|
from urllib.parse import urlparse
|
|
756
761
|
|
|
@@ -763,26 +768,35 @@ def _download_manifest(resolved, *, offline: bool):
|
|
|
763
768
|
parsed = urlparse(url)
|
|
764
769
|
scheme = parsed.scheme.lower()
|
|
765
770
|
|
|
766
|
-
#
|
|
767
|
-
#
|
|
771
|
+
# ``file://`` URLs and bare filesystem paths (including Windows drive paths
|
|
772
|
+
# like ``C:\bundle.yml``, which urlparse reads as a single-letter scheme)
|
|
773
|
+
# are not valid catalog download URLs. Catalog URLs are HTTPS-only across
|
|
774
|
+
# every catalog system; installing from disk is done by passing the path
|
|
775
|
+
# positionally, which never reaches URL resolution. Give an actionable
|
|
776
|
+
# error rather than accepting a scheme the rest of the codebase rejects.
|
|
768
777
|
if scheme in ("", "file") or re.match(r"^[A-Za-z]:[\\/]", url):
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
raise BundlerError(
|
|
778
|
-
f"Network access disabled; cannot download bundle '{resolved.entry.id}' "
|
|
779
|
-
f"from {url}."
|
|
780
|
-
)
|
|
781
|
-
return _download_remote_manifest(resolved.entry.id, url)
|
|
778
|
+
raise BundlerError(
|
|
779
|
+
f"Catalog entry '{resolved.entry.id}' has a non-HTTP(S) download_url "
|
|
780
|
+
f"({url}); catalog download URLs must be HTTPS (http for localhost) — "
|
|
781
|
+
"a file:// URL, a local filesystem path, or a scheme-less value "
|
|
782
|
+
"(e.g. 'example.com/bundle.zip') is not accepted. "
|
|
783
|
+
"To install a bundle from disk, pass the path directly: "
|
|
784
|
+
"'specify bundle install <path-to-bundle.yml | bundle-dir | .zip>'."
|
|
785
|
+
)
|
|
782
786
|
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
787
|
+
# Validate the scheme/host *before* the offline gate so an invalid or
|
|
788
|
+
# non-HTTPS download_url reports the real problem in every mode, rather
|
|
789
|
+
# than a misleading "Network access disabled" under --offline.
|
|
790
|
+
# (_download_remote_manifest re-checks this, but only once network access
|
|
791
|
+
# is permitted.) HTTPS-only, http allowed for localhost.
|
|
792
|
+
_require_https(f"bundle '{resolved.entry.id}'", url)
|
|
793
|
+
|
|
794
|
+
if offline:
|
|
795
|
+
raise BundlerError(
|
|
796
|
+
f"Network access disabled; cannot download bundle '{resolved.entry.id}' "
|
|
797
|
+
f"from {url}."
|
|
798
|
+
)
|
|
799
|
+
return _download_remote_manifest(resolved.entry.id, url)
|
|
786
800
|
|
|
787
801
|
|
|
788
802
|
def _require_https(label: str, url: str) -> None:
|
|
@@ -1078,6 +1078,11 @@ class ExtensionManager:
|
|
|
1078
1078
|
frontmatter = registrar._adjust_script_paths(
|
|
1079
1079
|
frontmatter, extension_id=manifest.id
|
|
1080
1080
|
)
|
|
1081
|
+
# Mirror the register_commands() rewrite (#2101): resolve
|
|
1082
|
+
# extension-relative subdir references (agents/, knowledge-base/,
|
|
1083
|
+
# etc.) to their installed .specify/extensions/<id>/ location
|
|
1084
|
+
# before the generic placeholder/path resolution below.
|
|
1085
|
+
body = registrar.rewrite_extension_paths(body, manifest.id, extension_dir)
|
|
1081
1086
|
body = registrar.resolve_skill_placeholders(
|
|
1082
1087
|
selected_ai, frontmatter, body, self.project_root, extension_id=manifest.id
|
|
1083
1088
|
)
|
|
@@ -2755,18 +2760,32 @@ class ConfigManager:
|
|
|
2755
2760
|
if not key.startswith(prefix):
|
|
2756
2761
|
continue
|
|
2757
2762
|
|
|
2758
|
-
# Remove prefix and split into parts
|
|
2759
|
-
|
|
2763
|
+
# Remove prefix and split into parts. Drop empty components from a
|
|
2764
|
+
# malformed name (e.g. ``SPECKIT_<EXT>_`` with no key, or
|
|
2765
|
+
# consecutive underscores ``SPECKIT_X__Y``) so we never create an
|
|
2766
|
+
# entry under an empty key.
|
|
2767
|
+
config_path = [p for p in key[len(prefix) :].lower().split("_") if p]
|
|
2768
|
+
if not config_path:
|
|
2769
|
+
continue
|
|
2760
2770
|
|
|
2761
|
-
# Build nested dict
|
|
2771
|
+
# Build nested dict. Two env vars can collide on a prefix, e.g.
|
|
2772
|
+
# SPECKIT_X_CONNECTION=a and SPECKIT_X_CONNECTION_URL=b. Guard the
|
|
2773
|
+
# walk so a colliding scalar is replaced by a dict (deeper/more
|
|
2774
|
+
# specific vars win) instead of being indexed into — which raised
|
|
2775
|
+
# TypeError ('str' object does not support item assignment) — and
|
|
2776
|
+
# guard the leaf so a scalar processed after the nested var does
|
|
2777
|
+
# not clobber the nested dict. Order-independent: both insertion
|
|
2778
|
+
# orders yield {'connection': {'url': ...}}. Nested-wins mirrors
|
|
2779
|
+
# _merge_configs' dict-preserving semantics.
|
|
2762
2780
|
current = env_config
|
|
2763
2781
|
for part in config_path[:-1]:
|
|
2764
|
-
if
|
|
2782
|
+
if not isinstance(current.get(part), dict):
|
|
2765
2783
|
current[part] = {}
|
|
2766
2784
|
current = current[part]
|
|
2767
2785
|
|
|
2768
|
-
# Set the final value
|
|
2769
|
-
current
|
|
2786
|
+
# Set the final value, unless a nested dict already occupies it.
|
|
2787
|
+
if not isinstance(current.get(config_path[-1]), dict):
|
|
2788
|
+
current[config_path[-1]] = value
|
|
2770
2789
|
|
|
2771
2790
|
return env_config
|
|
2772
2791
|
|
|
@@ -1566,7 +1566,14 @@ def extension_set_priority(
|
|
|
1566
1566
|
raw_priority = metadata.get("priority")
|
|
1567
1567
|
# Only skip if the stored value is already a valid int equal to requested priority
|
|
1568
1568
|
# This ensures corrupted values (e.g., "high") get repaired even when setting to default (10)
|
|
1569
|
-
|
|
1569
|
+
# A bool is an int in Python (isinstance(True, int) is True), so exclude it explicitly —
|
|
1570
|
+
# mirroring normalize_priority's bool guard — otherwise a corrupted True/False priority
|
|
1571
|
+
# equals 1/0 here and is never repaired.
|
|
1572
|
+
if (
|
|
1573
|
+
isinstance(raw_priority, int)
|
|
1574
|
+
and not isinstance(raw_priority, bool)
|
|
1575
|
+
and raw_priority == priority
|
|
1576
|
+
):
|
|
1570
1577
|
console.print(f"[yellow]Extension '{_escape_markup(str(display_name))}' already has priority {priority}[/yellow]")
|
|
1571
1578
|
raise typer.Exit(0)
|
|
1572
1579
|
|
|
@@ -778,6 +778,7 @@ class PresetManager:
|
|
|
778
778
|
matching_cmds, ext_id, ext_dir,
|
|
779
779
|
self.project_root,
|
|
780
780
|
context_note=f"\n<!-- Extension: {ext_id} -->\n<!-- Config: .specify/extensions/{ext_id}/ -->\n",
|
|
781
|
+
extension_id=ext_id,
|
|
781
782
|
)
|
|
782
783
|
registered = True
|
|
783
784
|
except Exception:
|
|
@@ -1199,6 +1200,8 @@ class PresetManager:
|
|
|
1199
1200
|
"command_name": cmd_name,
|
|
1200
1201
|
"source_file": source_file,
|
|
1201
1202
|
"source": f"extension:{manifest.id}",
|
|
1203
|
+
"extension_id": manifest.id,
|
|
1204
|
+
"extension_dir": ext_root,
|
|
1202
1205
|
}
|
|
1203
1206
|
modern_skill_name, legacy_skill_name = self._skill_names_for_command(cmd_name)
|
|
1204
1207
|
restore_index.setdefault(modern_skill_name, restore_info)
|
|
@@ -1463,6 +1466,17 @@ class PresetManager:
|
|
|
1463
1466
|
if extension_restore:
|
|
1464
1467
|
content = extension_restore["source_file"].read_text(encoding="utf-8")
|
|
1465
1468
|
frontmatter, body = registrar.parse_frontmatter(content)
|
|
1469
|
+
# Mirror the register-time rewrite (#2101): resolve
|
|
1470
|
+
# extension-relative subdir references (agents/,
|
|
1471
|
+
# knowledge-base/, etc.) to their installed location before
|
|
1472
|
+
# the generic placeholder resolution below, otherwise
|
|
1473
|
+
# restoring after a preset override removal would leave
|
|
1474
|
+
# bare, unresolvable paths in the skill body.
|
|
1475
|
+
body = registrar.rewrite_extension_paths(
|
|
1476
|
+
body,
|
|
1477
|
+
extension_restore["extension_id"],
|
|
1478
|
+
extension_restore["extension_dir"],
|
|
1479
|
+
)
|
|
1466
1480
|
if isinstance(selected_ai, str):
|
|
1467
1481
|
body = registrar.resolve_skill_placeholders(
|
|
1468
1482
|
selected_ai, frontmatter, body, self.project_root
|
|
@@ -3038,6 +3052,8 @@ class PresetResolver:
|
|
|
3038
3052
|
"path": candidate,
|
|
3039
3053
|
"source": source,
|
|
3040
3054
|
"strategy": "replace",
|
|
3055
|
+
"extension_id": ext_id,
|
|
3056
|
+
"extension_dir": ext_dir,
|
|
3041
3057
|
})
|
|
3042
3058
|
|
|
3043
3059
|
# Priority 4: Core templates (always "replace")
|
|
@@ -3157,10 +3173,32 @@ class PresetResolver:
|
|
|
3157
3173
|
if not layers:
|
|
3158
3174
|
return None
|
|
3159
3175
|
|
|
3176
|
+
def _read_layer_content(layer: Dict[str, Any]) -> str:
|
|
3177
|
+
"""Read a layer's raw text, rewriting extension-relative subdir
|
|
3178
|
+
references (agents/, knowledge-base/, etc.) to their installed
|
|
3179
|
+
location when the layer is extension-provided (#2101).
|
|
3180
|
+
|
|
3181
|
+
Extension layers are always inserted with strategy "replace"
|
|
3182
|
+
(see collect_all_layers), so a layer only ever needs this
|
|
3183
|
+
rewrite when it wins outright above or serves as the
|
|
3184
|
+
composition base below — never as a mid-stack composing
|
|
3185
|
+
(append/prepend/wrap) layer.
|
|
3186
|
+
"""
|
|
3187
|
+
text = layer["path"].read_text(encoding="utf-8")
|
|
3188
|
+
extension_id = layer.get("extension_id")
|
|
3189
|
+
extension_dir = layer.get("extension_dir")
|
|
3190
|
+
if extension_id and extension_dir:
|
|
3191
|
+
from ..agents import CommandRegistrar
|
|
3192
|
+
|
|
3193
|
+
text = CommandRegistrar.rewrite_extension_paths(
|
|
3194
|
+
text, extension_id, extension_dir
|
|
3195
|
+
)
|
|
3196
|
+
return text
|
|
3197
|
+
|
|
3160
3198
|
# If the top (highest-priority) layer is replace, it wins entirely —
|
|
3161
3199
|
# lower layers are irrelevant regardless of their strategies.
|
|
3162
3200
|
if layers[0]["strategy"] == "replace":
|
|
3163
|
-
return layers[0]
|
|
3201
|
+
return _read_layer_content(layers[0])
|
|
3164
3202
|
|
|
3165
3203
|
# Composition: build content bottom-up from the effective base.
|
|
3166
3204
|
# The base is the nearest replace layer scanning from highest priority
|
|
@@ -3183,7 +3221,7 @@ class PresetResolver:
|
|
|
3183
3221
|
|
|
3184
3222
|
# Convert to reversed_layers index
|
|
3185
3223
|
base_reversed_idx = len(layers) - 1 - base_layer_idx
|
|
3186
|
-
content = layers[base_layer_idx]
|
|
3224
|
+
content = _read_layer_content(layers[base_layer_idx])
|
|
3187
3225
|
# Compose only the layers above the base (higher priority = lower index in layers,
|
|
3188
3226
|
# higher index in reversed_layers). Process bottom-up from base+1.
|
|
3189
3227
|
start_idx = base_reversed_idx + 1
|
|
@@ -469,7 +469,14 @@ def preset_set_priority(
|
|
|
469
469
|
raw_priority = metadata.get("priority")
|
|
470
470
|
# Only skip if the stored value is already a valid int equal to requested priority
|
|
471
471
|
# This ensures corrupted values (e.g., "high") get repaired even when setting to default (10)
|
|
472
|
-
|
|
472
|
+
# A bool is an int in Python (isinstance(True, int) is True), so exclude it explicitly —
|
|
473
|
+
# mirroring normalize_priority's bool guard — otherwise a corrupted True/False priority
|
|
474
|
+
# equals 1/0 here and is never repaired.
|
|
475
|
+
if (
|
|
476
|
+
isinstance(raw_priority, int)
|
|
477
|
+
and not isinstance(raw_priority, bool)
|
|
478
|
+
and raw_priority == priority
|
|
479
|
+
):
|
|
473
480
|
console.print(f"[yellow]Preset '{preset_id}' already has priority {priority}[/yellow]")
|
|
474
481
|
raise typer.Exit(0)
|
|
475
482
|
|
|
@@ -76,8 +76,16 @@ class WorkflowRegistry:
|
|
|
76
76
|
if self.registry_path.exists():
|
|
77
77
|
try:
|
|
78
78
|
with open(self.registry_path, encoding="utf-8") as f:
|
|
79
|
-
|
|
80
|
-
|
|
79
|
+
data = json.load(f)
|
|
80
|
+
# Validate shape: must be a dict with a dict "workflows" field,
|
|
81
|
+
# otherwise every method that indexes data["workflows"] crashes.
|
|
82
|
+
# Mirrors StepRegistry._load.
|
|
83
|
+
if not isinstance(data, dict):
|
|
84
|
+
return {"schema_version": self.SCHEMA_VERSION, "workflows": {}}
|
|
85
|
+
if not isinstance(data.get("workflows"), dict):
|
|
86
|
+
data["workflows"] = {}
|
|
87
|
+
return data
|
|
88
|
+
except (json.JSONDecodeError, ValueError, OSError, UnicodeError):
|
|
81
89
|
# Corrupted registry file — reset to default
|
|
82
90
|
return {"schema_version": self.SCHEMA_VERSION, "workflows": {}}
|
|
83
91
|
return {"schema_version": self.SCHEMA_VERSION, "workflows": {}}
|
|
@@ -438,9 +446,9 @@ class WorkflowCatalog:
|
|
|
438
446
|
q = query.lower()
|
|
439
447
|
searchable = " ".join(
|
|
440
448
|
[
|
|
441
|
-
wf_data.get("name"
|
|
442
|
-
wf_data.get("description"
|
|
443
|
-
wf_data.get("id"
|
|
449
|
+
str(wf_data.get("name") or ""),
|
|
450
|
+
str(wf_data.get("description") or ""),
|
|
451
|
+
str(wf_data.get("id") or ""),
|
|
444
452
|
]
|
|
445
453
|
).lower()
|
|
446
454
|
if q not in searchable:
|
|
@@ -982,7 +982,16 @@ class WorkflowEngine:
|
|
|
982
982
|
from .expressions import evaluate_condition
|
|
983
983
|
|
|
984
984
|
max_iters = step_config.get("max_iterations")
|
|
985
|
-
|
|
985
|
+
# A bool is an int in Python (isinstance(True, int) is True
|
|
986
|
+
# and True == 1), so a bool max_iterations would slip past
|
|
987
|
+
# the int check and cap the loop at range(0)==1 iteration
|
|
988
|
+
# instead of the default. Exclude bools, mirroring the
|
|
989
|
+
# while/do-while validators and the continue_on_error guard.
|
|
990
|
+
if (
|
|
991
|
+
isinstance(max_iters, bool)
|
|
992
|
+
or not isinstance(max_iters, int)
|
|
993
|
+
or max_iters < 1
|
|
994
|
+
):
|
|
986
995
|
max_iters = 10
|
|
987
996
|
condition = step_config.get("condition", False)
|
|
988
997
|
for _loop_iter in range(max_iters - 1):
|