specify-cli 0.12.14__tar.gz → 0.12.15__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.14 → specify_cli-0.12.15}/CHANGELOG.md +15 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/PKG-INFO +1 -1
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/community/extensions.md +2 -1
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/community/presets.md +1 -1
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/reference/workflows.md +26 -3
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/catalog.community.json +54 -4
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/catalog.community.json +8 -7
- {specify_cli-0.12.14 → specify_cli-0.12.15}/pyproject.toml +1 -1
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/_github_http.py +30 -5
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/_init_options.py +1 -1
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/lib/yamlio.py +50 -2
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/services/installer.py +32 -10
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/extensions/__init__.py +65 -1
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/base.py +31 -3
- specify_cli-0.12.15/src/specify_cli/workflows/_commands.py +3153 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/catalog.py +215 -30
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/engine.py +118 -5
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/contract/test_bundle_cli.py +39 -11
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integration/test_bundler_install_flow.py +208 -2
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_base_yaml.py +30 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_extensions.py +132 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_github_http.py +38 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_presets.py +5 -44
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_workflows.py +5119 -74
- specify_cli-0.12.14/src/specify_cli/workflows/_commands.py +0 -1729
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.devcontainer/devcontainer.json +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.devcontainer/post-create.sh +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.editorconfig +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.gitattributes +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/CODEOWNERS +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/ISSUE_TEMPLATE/agent_request.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/ISSUE_TEMPLATE/bundle_submission.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/ISSUE_TEMPLATE/extension_submission.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/ISSUE_TEMPLATE/preset_submission.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/aw/actions-lock.json +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/dependabot.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/skills/add-community-extension/SKILL.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/RELEASE-PROCESS.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/add-community-extension.lock.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/add-community-extension.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/add-community-preset.lock.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/add-community-preset.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/bug-assess.lock.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/bug-assess.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/bug-fix.lock.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/bug-fix.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/bug-test.lock.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/bug-test.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/catalog-assign.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/codeql.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/docs.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/lint.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/publish-pypi.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/release-trigger.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/release.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/stale.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.github/workflows/test.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.gitignore +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.markdownlint-cli2.jsonc +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.pre-commit-config.yaml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/.zenodo.json +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/AGENTS.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/CITATION.cff +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/CODE_OF_CONDUCT.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/CONTRIBUTING.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/DEVELOPMENT.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/LICENSE +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/SECURITY.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/SUPPORT.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/.gitignore +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/community/bundles.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/community/friends.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/community/overview.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/community/walkthroughs.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/concepts/complex-features.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/concepts/sdd.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/concepts/spec-persistence.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/docfx.json +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/guides/evolving-specs.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/guides/monorepo.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/index.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/install/air-gapped.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/install/one-time.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/install/pipx.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/install/uv.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/installation.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/local-development.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/quickstart.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/reference/authentication.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/reference/bundles.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/reference/core.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/reference/extensions.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/reference/integrations.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/reference/overview.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/reference/presets.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/template/public/main.css +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/toc.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/docs/upgrade.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/examples/bundles/business-analyst/README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/examples/bundles/business-analyst/bundle.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/examples/bundles/developer/README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/examples/bundles/developer/bundle.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/examples/bundles/product-manager/README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/examples/bundles/product-manager/bundle.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/examples/bundles/security-researcher/README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/examples/bundles/security-researcher/bundle.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/EXTENSION-API-REFERENCE.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/EXTENSION-DEVELOPMENT-GUIDE.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/EXTENSION-PUBLISHING-GUIDE.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/EXTENSION-USER-GUIDE.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/RFC-EXTENSION-SYSTEM.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/agent-context/README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/agent-context/agent-context-config.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/agent-context/agent-context-defaults.json +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/agent-context/commands/speckit.agent-context.update.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/agent-context/extension.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/agent-context/scripts/bash/update-agent-context.sh +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/agent-context/scripts/powershell/update-agent-context.ps1 +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/agent-context/scripts/python/update_agent_context.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/bug/README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/bug/commands/speckit.bug.assess.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/bug/commands/speckit.bug.fix.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/bug/commands/speckit.bug.test.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/bug/extension.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/catalog.json +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/commands/speckit.git.commit.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/commands/speckit.git.feature.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/commands/speckit.git.initialize.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/commands/speckit.git.remote.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/commands/speckit.git.validate.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/config-template.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/extension.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/git-config.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/scripts/bash/auto-commit.sh +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/scripts/bash/create-new-feature-branch.sh +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/scripts/bash/git-common.sh +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/scripts/bash/initialize-repo.sh +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/scripts/powershell/auto-commit.ps1 +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/scripts/powershell/create-new-feature-branch.ps1 +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/scripts/powershell/git-common.ps1 +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/git/scripts/powershell/initialize-repo.ps1 +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/selftest/commands/selftest.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/selftest/extension.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/template/.gitignore +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/template/CHANGELOG.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/template/EXAMPLE-README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/template/LICENSE +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/template/README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/template/commands/example.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/template/config-template.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/extensions/template/extension.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/integrations/CONTRIBUTING.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/integrations/README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/integrations/catalog.community.json +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/integrations/catalog.json +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/media/bootstrap-claude-code.gif +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/media/logo_large.webp +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/media/logo_small.webp +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/media/spec-kit-video-header.jpg +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/media/specify_cli.gif +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/newsletters/2026-April.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/newsletters/2026-February.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/newsletters/2026-June.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/newsletters/2026-March.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/newsletters/2026-May.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/ARCHITECTURE.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/PUBLISHING.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/catalog.json +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/lean/README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/lean/commands/speckit.constitution.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/lean/commands/speckit.implement.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/lean/commands/speckit.plan.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/lean/commands/speckit.specify.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/lean/commands/speckit.tasks.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/lean/preset.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/scaffold/README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/scaffold/commands/speckit.myext.myextcmd.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/scaffold/commands/speckit.specify.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/scaffold/preset.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/scaffold/templates/myext-template.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/scaffold/templates/spec-template.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/self-test/commands/speckit.specify.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/self-test/commands/speckit.wrap-test.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/self-test/preset.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/self-test/templates/checklist-template.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/self-test/templates/constitution-template.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/self-test/templates/plan-template.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/self-test/templates/spec-template.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/presets/self-test/templates/tasks-template.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/scripts/bash/check-prerequisites.sh +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/scripts/bash/common.sh +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/scripts/bash/create-new-feature.sh +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/scripts/bash/setup-plan.sh +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/scripts/bash/setup-tasks.sh +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/scripts/powershell/check-prerequisites.ps1 +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/scripts/powershell/common.ps1 +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/scripts/powershell/create-new-feature.ps1 +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/scripts/powershell/setup-plan.ps1 +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/scripts/powershell/setup-tasks.ps1 +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/scripts/python/check_prerequisites.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/scripts/python/common.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/spec-driven.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/spec-kit.code-workspace +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/_agent_config.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/_assets.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/_console.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/_invocation_style.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/_project.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/_toml_string.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/_utils.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/_version.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/agents.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/authentication/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/authentication/azure_devops.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/authentication/base.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/authentication/config.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/authentication/github.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/authentication/http.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/commands_impl/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/commands_impl/catalog_config.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/lib/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/lib/project.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/lib/versioning.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/models/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/models/catalog.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/models/manifest.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/models/records.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/services/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/services/adapters.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/services/catalog_stack.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/services/conflict.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/services/packager.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/services/primitives.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/services/references.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/services/resolver.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/bundler/services/validator.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/catalogs.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/commands/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/commands/bundle/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/commands/init.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/extensions/_commands.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integration_runtime.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integration_scaffold.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integration_state.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integration_status.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/_commands.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/_helpers.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/_install_commands.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/_migrate_commands.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/_query_commands.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/_scaffold_commands.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/agy/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/amp/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/auggie/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/bob/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/catalog.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/claude/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/cline/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/codebuddy/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/codex/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/copilot/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/cursor_agent/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/devin/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/firebender/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/forge/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/gemini/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/generic/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/goose/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/hermes/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/junie/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/kilocode/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/kimi/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/kiro_cli/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/lingma/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/manifest.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/omp/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/opencode/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/pi/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/qodercli/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/qwen/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/rovodev/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/shai/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/tabnine/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/trae/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/vibe/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/zcode/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/integrations/zed/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/presets/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/presets/_commands.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/shared_infra.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/base.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/expressions.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/steps/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/steps/command/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/steps/do_while/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/steps/fan_in/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/steps/fan_out/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/steps/gate/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/steps/if_then/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/steps/init/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/steps/prompt/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/steps/shell/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/steps/switch/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/src/specify_cli/workflows/steps/while_loop/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/templates/checklist-template.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/templates/commands/analyze.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/templates/commands/checklist.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/templates/commands/clarify.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/templates/commands/constitution.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/templates/commands/converge.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/templates/commands/implement.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/templates/commands/plan.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/templates/commands/specify.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/templates/commands/tasks.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/templates/commands/taskstoissues.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/templates/constitution-template.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/templates/plan-template.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/templates/spec-template.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/templates/tasks-template.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/templates/vscode-settings.json +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/auth_helpers.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/bundler_helpers.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/conftest.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/contract/test_catalog_schema.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/contract/test_manifest_schema.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/extensions/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/extensions/bug/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/extensions/bug/test_bug_extension.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/extensions/git/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/extensions/git/test_git_extension.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/extensions/test_agent_context_cli_free.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/extensions/test_extension_agent_context.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/extensions/test_update_agent_context_feature_json.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/extensions/test_update_agent_context_python_parity.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/hooks/TESTING.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/hooks/plan.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/hooks/spec.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/hooks/tasks.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/http_helpers.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integration/test_bundler_catalog_stack.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integration/test_bundler_init_install.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integration/test_bundler_local_install.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integration/test_bundler_offline.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integration/test_bundler_security_paths.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/__init__.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/conftest.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_base.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_cli.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_extra_args.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_home_isolation.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_agy.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_amp.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_auggie.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_base_markdown.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_base_skills.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_base_toml.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_bob.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_catalog.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_claude.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_cline.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_codebuddy.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_codex.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_copilot.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_cursor_agent.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_devin.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_firebender.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_forge.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_gemini.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_generic.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_goose.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_hermes.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_junie.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_kilocode.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_kimi.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_kiro_cli.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_lingma.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_omp.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_opencode.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_pi.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_qodercli.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_qwen.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_rovodev.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_scaffold.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_shai.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_state.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_subcommand.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_tabnine.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_trae.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_vibe.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_zcode.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_integration_zed.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_manifest.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_registry.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/integrations/test_skill_frontmatter_quoting.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/self_upgrade_helpers.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_agent_config_consistency.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_authentication.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_branch_numbering.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_check_prerequisites_paths_only.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_check_prerequisites_python_parity.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_check_tool.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_cli_version.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_command_template_py_scripts.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_commands_package.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_console_imports.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_extension_registration.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_extension_skills.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_extension_update_hardening.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_github_workflows.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_init_dir.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_init_dir_cli.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_live_transient_windows.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_merge.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_post_process.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_ps1_encoding.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_registrar_path_traversal.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_self_upgrade_detection.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_self_upgrade_execution.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_self_upgrade_guidance.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_self_upgrade_verification.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_setup_plan_feature_json.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_setup_plan_no_overwrite.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_setup_tasks.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_shared_infra_integrity.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_timestamp_branches.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_upgrade.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_utils.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_utils_assets_imports.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_version_imports.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/test_workflow_run_without_project.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/unit/test_bundler_adapters.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/unit/test_bundler_catalog_config.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/unit/test_bundler_conflict.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/unit/test_bundler_packager.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/unit/test_bundler_primitives.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/unit/test_bundler_records.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/unit/test_bundler_references.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/unit/test_bundler_resolver.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/unit/test_bundler_validator.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/tests/unit/test_bundler_versioning.py +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/workflows/ARCHITECTURE.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/workflows/PUBLISHING.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/workflows/README.md +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/workflows/catalog.community.json +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/workflows/catalog.json +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/workflows/speckit/workflow.yml +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/workflows/step-catalog.community.json +0 -0
- {specify_cli-0.12.14 → specify_cli-0.12.15}/workflows/step-catalog.json +0 -0
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- insert new changelog below this comment -->
|
|
4
4
|
|
|
5
|
+
## [0.12.15] - 2026-07-14
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Update Autonomous Run Governance preset to v0.1.4 (#3511)
|
|
10
|
+
- fix(workflows): raise catalog error, not raw ValueError, on a malformed catalog URL (#3484)
|
|
11
|
+
- fix(workflows): evaluate 'in'/'not in' safely on a non-iterable right operand (#3447) (#3468)
|
|
12
|
+
- fix: add trailing newline to init-options.json output (#3509)
|
|
13
|
+
- feat(workflows): align workflow CLI with extension command surface (#3419)
|
|
14
|
+
- fix(extensions): stop env-var config leaking across prefix-colliding extension IDs (#3497)
|
|
15
|
+
- fix(integrations): escape control characters in goose recipe YAML renderer (#3384)
|
|
16
|
+
- [extension] Update DocGuard — CDD Enforcement extension to v0.32.0 (#3489)
|
|
17
|
+
- [extension] Add Multi-Repo Branch Sync extension to community catalog (#3411)
|
|
18
|
+
- chore: release 0.12.14, begin 0.12.15.dev0 development (#3506)
|
|
19
|
+
|
|
5
20
|
## [0.12.14] - 2026-07-13
|
|
6
21
|
|
|
7
22
|
### Changed
|
|
@@ -51,7 +51,7 @@ The following community-contributed extensions are available in [`catalog.commun
|
|
|
51
51
|
| Confluence Extension | Create a doc in Confluence summarizing the specifications and planning files | `integration` | Read+Write | [spec-kit-confluence](https://github.com/aaronrsun/spec-kit-confluence) |
|
|
52
52
|
| Cost Tracker | Track real LLM dollar cost across SDD workflows — per-feature budgets, per-integration comparison, and finance-ready exports | `visibility` | Read+Write | [spec-kit-cost](https://github.com/Quratulain-bilal/spec-kit-cost) |
|
|
53
53
|
| Data Model Diagram | Generates Mermaid ER diagrams from Spec Kit data models after planning | `docs` | Read+Write | [spec-kit-data-model-diagram](https://github.com/benizzio/spec-kit-data-model-diagram) |
|
|
54
|
-
| DocGuard — CDD Enforcement |
|
|
54
|
+
| DocGuard — CDD Enforcement | Doc-integrity engine with MCP server, SARIF output, and zero-LLM core. Validates, scores, and traces documentation against code — 24 validators, stable finding codes, spec-kit hooks. Pure Node.js. | `docs` | Read+Write | [spec-kit-docguard](https://github.com/raccioly/docguard) |
|
|
55
55
|
| 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) |
|
|
56
56
|
| Extensify | Create and validate extensions and extension catalogs | `process` | Read+Write | [extensify](https://github.com/mnriem/spec-kit-extensions/tree/main/extensify) |
|
|
57
57
|
| 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) |
|
|
@@ -84,6 +84,7 @@ The following community-contributed extensions are available in [`catalog.commun
|
|
|
84
84
|
| MemoryLint | Evidence-driven instruction drift checker: audits agent memory files for boundary, reality, conflict, and redundancy drift. | `process` | Read+Write | [memorylint](https://github.com/RbBtSn0w/spec-kit-extensions/tree/main/memorylint) |
|
|
85
85
|
| Microsoft 365 Integration | Fetch Teams messages, meeting transcripts, and SharePoint/OneDrive files as local Markdown for spec generation | `integration` | Read+Write | [spec-kit-m365](https://github.com/BenBtg/spec-kit-m365) |
|
|
86
86
|
| Multi-Model Review | Cross-model Spec Kit handoffs for spec authoring, implementation routing, and review. | `process` | Read+Write | [multi-model-review](https://github.com/formin/multi-model-review) |
|
|
87
|
+
| Multi-Repo Branch Sync | Creates the feature branch in affected sub-repositories and git submodules via plan/tasks hooks | `process` | Read+Write | [multi-repo-sync](https://github.com/fyloss/spec-kit-multi-repo-sync) |
|
|
87
88
|
| Multi-Sites Spec Kit | Multi-site aware specify command with per-site spec folders, auto-increment, and Drupal support | `process` | Read+Write | [spec-kit-multi-sites](https://github.com/teeyo/spec-kit-multi-sites) |
|
|
88
89
|
| .NET Framework to Modern .NET Migration | Orchestrate end-to-end .NET Framework to modern .NET migration across 7 phases, with SDD lifecycle integration | `process` | Read+Write | [spec-kit-fx-to-net](https://github.com/RogerBestMsft/spec-kit-FxToNet) |
|
|
89
90
|
| Onboard | Contextual onboarding and progressive growth for developers new to spec-kit projects. Explains specs, maps dependencies, validates understanding, and guides the next step | `process` | Read+Write | [spec-kit-onboard](https://github.com/dmux/spec-kit-onboard) |
|
|
@@ -11,7 +11,7 @@ The following community-contributed presets customize how Spec Kit behaves — o
|
|
|
11
11
|
| Agent Parity Governance | Adds shared-guidance parity, audit-ready Spec-Kit run evidence, and agent-neutral model-routing guidance across a project's declared AI-agent instruction surfaces so agent guidance does not drift. | 6 templates, 3 commands | — | [spec-kit-preset-agent-parity-governance](https://github.com/hindermath/spec-kit-preset-agent-parity-governance) |
|
|
12
12
|
| AIDE In-Place Migration | Adapts the AIDE extension workflow for in-place technology migrations (X → Y pattern) — adds migration objectives, verification gates, knowledge documents, and behavioral equivalence criteria | 2 templates, 8 commands | AIDE extension | [spec-kit-presets](https://github.com/mnriem/spec-kit-presets) |
|
|
13
13
|
| Architecture Governance | Adds secure software architecture, STRIDE+CAPEC threat modeling, arc42 security cross-cutting concepts, S-ADRs, Zero Trust applicability, OWASP SAMM governance, BSI C3A cloud autonomy, BSI C5 cloud compliance assurance, and audit-ready Spec Kit run evidence | 13 templates, 3 commands | — | [spec-kit-preset-architecture-governance](https://github.com/hindermath/spec-kit-preset-architecture-governance) |
|
|
14
|
-
| Autonomous Run Governance | Adds permission-bounded, evidence-first governance for autonomous Spec Kit delivery, convergence, resume, closeout, and retrospective learning. |
|
|
14
|
+
| Autonomous Run Governance | Adds permission-bounded, evidence-first governance for autonomous Spec Kit delivery, convergence, resume, closeout, and retrospective learning. | 12 templates, 2 commands, 2 scripts | — | [spec-kit-preset-autonomous-run-governance](https://github.com/hindermath/spec-kit-preset-autonomous-run-governance) |
|
|
15
15
|
| Canon Core | Adapts original Spec Kit workflow to work together with Canon extension | 2 templates, 8 commands | — | [spec-kit-canon](https://github.com/maximiliamus/spec-kit-canon) |
|
|
16
16
|
| Claude AskUserQuestion | Upgrades `/speckit.clarify` and `/speckit.checklist` on Claude Code from Markdown-table prompts to the native AskUserQuestion picker, with a recommended option and reasoning on every question | 2 commands | — | [spec-kit-preset-claude-ask-questions](https://github.com/0xrafasec/spec-kit-preset-claude-ask-questions) |
|
|
17
17
|
| Command Density | Compacts the nine core Spec Kit command prompts while preserving scripts, handoffs, placeholders, hook output blocks, and rule structure | 9 commands | — | [spec-kit-preset-command-density](https://github.com/Xopoko/spec-kit-preset-command-density) |
|
|
@@ -86,8 +86,30 @@ Lists workflows installed in the current project.
|
|
|
86
86
|
specify workflow add <source>
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
+
| Option | Description |
|
|
90
|
+
| --------------- | ------------------------------------------------------ |
|
|
91
|
+
| `--dev` | Install from a local workflow YAML file or directory |
|
|
92
|
+
| `--from <url>` | Install from a custom URL (`<source>` names the expected workflow ID) |
|
|
93
|
+
|
|
89
94
|
Installs a workflow from the catalog, a URL (HTTPS required), or a local file path.
|
|
90
95
|
|
|
96
|
+
## Update Workflows
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
specify workflow update [workflow_id]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Updates one installed catalog workflow — or all of them when no ID is given — to the latest catalog version. Prompts for confirmation and keeps the installed copy if a download or validation fails.
|
|
103
|
+
|
|
104
|
+
## Enable or Disable a Workflow
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
specify workflow enable <workflow_id>
|
|
108
|
+
specify workflow disable <workflow_id>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Disabled workflows stay installed and listed (marked `[disabled]`) but refuse to run until re-enabled.
|
|
112
|
+
|
|
91
113
|
## Remove a Workflow
|
|
92
114
|
|
|
93
115
|
```bash
|
|
@@ -102,9 +124,10 @@ Removes an installed workflow from the project.
|
|
|
102
124
|
specify workflow search [query]
|
|
103
125
|
```
|
|
104
126
|
|
|
105
|
-
| Option
|
|
106
|
-
|
|
|
107
|
-
| `--tag`
|
|
127
|
+
| Option | Description |
|
|
128
|
+
| ---------- | ----------------- |
|
|
129
|
+
| `--tag` | Filter by tag |
|
|
130
|
+
| `--author` | Filter by author |
|
|
108
131
|
|
|
109
132
|
Searches all active catalogs for workflows matching the query.
|
|
110
133
|
|
|
@@ -1106,10 +1106,10 @@
|
|
|
1106
1106
|
"docguard": {
|
|
1107
1107
|
"name": "DocGuard — CDD Enforcement",
|
|
1108
1108
|
"id": "docguard",
|
|
1109
|
-
"description": "
|
|
1109
|
+
"description": "Doc-integrity engine with MCP server, SARIF output, and zero-LLM core. Validates, scores, and traces documentation against code — 24 validators, stable finding codes, spec-kit hooks. Pure Node.js.",
|
|
1110
1110
|
"author": "raccioly",
|
|
1111
|
-
"version": "0.
|
|
1112
|
-
"download_url": "https://github.com/raccioly/docguard/releases/download/v0.
|
|
1111
|
+
"version": "0.32.0",
|
|
1112
|
+
"download_url": "https://github.com/raccioly/docguard/releases/download/v0.32.0/spec-kit-docguard-v0.32.0.zip",
|
|
1113
1113
|
"repository": "https://github.com/raccioly/docguard",
|
|
1114
1114
|
"homepage": "https://www.npmjs.com/package/docguard-cli",
|
|
1115
1115
|
"documentation": "https://github.com/raccioly/docguard/blob/main/extensions/spec-kit-docguard/README.md",
|
|
@@ -1124,6 +1124,14 @@
|
|
|
1124
1124
|
"name": "node",
|
|
1125
1125
|
"version": ">=18.0.0",
|
|
1126
1126
|
"required": true
|
|
1127
|
+
},
|
|
1128
|
+
{
|
|
1129
|
+
"name": "npx",
|
|
1130
|
+
"required": true
|
|
1131
|
+
},
|
|
1132
|
+
{
|
|
1133
|
+
"name": "specify",
|
|
1134
|
+
"required": false
|
|
1127
1135
|
}
|
|
1128
1136
|
]
|
|
1129
1137
|
},
|
|
@@ -1145,7 +1153,7 @@
|
|
|
1145
1153
|
"downloads": 0,
|
|
1146
1154
|
"stars": 0,
|
|
1147
1155
|
"created_at": "2026-03-13T00:00:00Z",
|
|
1148
|
-
"updated_at": "2026-07-
|
|
1156
|
+
"updated_at": "2026-07-13T00:00:00Z"
|
|
1149
1157
|
},
|
|
1150
1158
|
"doctor": {
|
|
1151
1159
|
"name": "Project Health Check",
|
|
@@ -2458,6 +2466,48 @@
|
|
|
2458
2466
|
"created_at": "2026-05-04T02:51:52Z",
|
|
2459
2467
|
"updated_at": "2026-06-18T00:00:00Z"
|
|
2460
2468
|
},
|
|
2469
|
+
"multi-repo-sync": {
|
|
2470
|
+
"name": "Multi-Repo Branch Sync",
|
|
2471
|
+
"id": "multi-repo-sync",
|
|
2472
|
+
"description": "Creates the feature branch in affected sub-repositories and git submodules via plan/tasks hooks",
|
|
2473
|
+
"author": "Fyloss",
|
|
2474
|
+
"version": "1.0.0",
|
|
2475
|
+
"download_url": "https://github.com/fyloss/spec-kit-multi-repo-sync/releases/download/v1.0.0/spec-kit-multi-repo-sync.zip",
|
|
2476
|
+
"sha256": "12a5c7392145b4424b20715aaa3d8b6a8218c143dea596873e344146c1a76ba0",
|
|
2477
|
+
"repository": "https://github.com/fyloss/spec-kit-multi-repo-sync",
|
|
2478
|
+
"homepage": "https://github.com/fyloss/spec-kit-multi-repo-sync",
|
|
2479
|
+
"documentation": "https://github.com/fyloss/spec-kit-multi-repo-sync/blob/main/README.md",
|
|
2480
|
+
"changelog": "https://github.com/fyloss/spec-kit-multi-repo-sync/blob/main/CHANGELOG.md",
|
|
2481
|
+
"license": "MIT",
|
|
2482
|
+
"category": "process",
|
|
2483
|
+
"effect": "read-write",
|
|
2484
|
+
"requires": {
|
|
2485
|
+
"speckit_version": ">=0.2.0",
|
|
2486
|
+
"tools": [
|
|
2487
|
+
{
|
|
2488
|
+
"name": "git",
|
|
2489
|
+
"version": ">=2.31",
|
|
2490
|
+
"required": true
|
|
2491
|
+
}
|
|
2492
|
+
]
|
|
2493
|
+
},
|
|
2494
|
+
"provides": {
|
|
2495
|
+
"commands": 3,
|
|
2496
|
+
"hooks": 2
|
|
2497
|
+
},
|
|
2498
|
+
"tags": [
|
|
2499
|
+
"git",
|
|
2500
|
+
"branching",
|
|
2501
|
+
"multi-repo",
|
|
2502
|
+
"submodules",
|
|
2503
|
+
"workflow"
|
|
2504
|
+
],
|
|
2505
|
+
"verified": false,
|
|
2506
|
+
"downloads": 0,
|
|
2507
|
+
"stars": 0,
|
|
2508
|
+
"created_at": "2026-07-13T00:00:00Z",
|
|
2509
|
+
"updated_at": "2026-07-13T00:00:00Z"
|
|
2510
|
+
},
|
|
2461
2511
|
"multi-sites": {
|
|
2462
2512
|
"name": "Multi-Sites Spec Kit",
|
|
2463
2513
|
"id": "multi-sites",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": "1.0",
|
|
3
|
-
"updated_at": "2026-07-
|
|
3
|
+
"updated_at": "2026-07-14T00:00:00Z",
|
|
4
4
|
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/presets/catalog.community.json",
|
|
5
5
|
"presets": {
|
|
6
6
|
"a11y-governance": {
|
|
@@ -134,20 +134,21 @@
|
|
|
134
134
|
"autonomous-run-governance": {
|
|
135
135
|
"name": "Autonomous Run Governance",
|
|
136
136
|
"id": "autonomous-run-governance",
|
|
137
|
-
"version": "0.1.
|
|
137
|
+
"version": "0.1.4",
|
|
138
138
|
"description": "Adds permission-bounded, evidence-first governance for autonomous Spec Kit delivery, convergence, resume, closeout, and retrospective learning.",
|
|
139
139
|
"author": "Thorsten Hindermann",
|
|
140
140
|
"repository": "https://github.com/hindermath/spec-kit-preset-autonomous-run-governance",
|
|
141
|
-
"download_url": "https://github.com/hindermath/spec-kit-preset-autonomous-run-governance/archive/refs/tags/v0.1.
|
|
141
|
+
"download_url": "https://github.com/hindermath/spec-kit-preset-autonomous-run-governance/archive/refs/tags/v0.1.4.zip",
|
|
142
142
|
"homepage": "https://github.com/hindermath/spec-kit-preset-autonomous-run-governance",
|
|
143
|
-
"documentation": "https://github.com/hindermath/spec-kit-preset-autonomous-run-governance/blob/
|
|
143
|
+
"documentation": "https://github.com/hindermath/spec-kit-preset-autonomous-run-governance/blob/v0.1.4/README.md",
|
|
144
144
|
"license": "MIT",
|
|
145
145
|
"requires": {
|
|
146
146
|
"speckit_version": ">=0.8.3"
|
|
147
147
|
},
|
|
148
148
|
"provides": {
|
|
149
|
-
"templates":
|
|
150
|
-
"commands": 2
|
|
149
|
+
"templates": 12,
|
|
150
|
+
"commands": 2,
|
|
151
|
+
"scripts": 2
|
|
151
152
|
},
|
|
152
153
|
"tags": [
|
|
153
154
|
"autonomous",
|
|
@@ -157,7 +158,7 @@
|
|
|
157
158
|
"retrospective"
|
|
158
159
|
],
|
|
159
160
|
"created_at": "2026-07-13T00:00:00Z",
|
|
160
|
-
"updated_at": "2026-07-
|
|
161
|
+
"updated_at": "2026-07-14T00:00:00Z"
|
|
161
162
|
},
|
|
162
163
|
"canon-core": {
|
|
163
164
|
"name": "Canon Core",
|
|
@@ -24,6 +24,7 @@ GITHUB_HOSTS = frozenset({
|
|
|
24
24
|
"api.github.com",
|
|
25
25
|
"codeload.github.com",
|
|
26
26
|
})
|
|
27
|
+
_MAX_RELEASE_METADATA_BYTES = 5 * 1024 * 1024
|
|
27
28
|
|
|
28
29
|
|
|
29
30
|
def build_github_request(url: str) -> urllib.request.Request:
|
|
@@ -68,6 +69,8 @@ def resolve_github_release_asset_api_url(
|
|
|
68
69
|
open_url_fn: Callable,
|
|
69
70
|
timeout: int = 60,
|
|
70
71
|
github_hosts: tuple[str, ...] = (),
|
|
72
|
+
redirect_validator: Callable[[str, str], None] | None = None,
|
|
73
|
+
max_metadata_bytes: int = _MAX_RELEASE_METADATA_BYTES,
|
|
71
74
|
) -> Optional[str]:
|
|
72
75
|
"""Resolve a GitHub release browser-download URL to its REST API asset URL.
|
|
73
76
|
|
|
@@ -91,6 +94,8 @@ def resolve_github_release_asset_api_url(
|
|
|
91
94
|
authenticated release-metadata lookup.
|
|
92
95
|
timeout: Per-request timeout in seconds.
|
|
93
96
|
github_hosts: Host patterns to treat as GitHub Enterprise Server.
|
|
97
|
+
redirect_validator: Optional policy applied to metadata redirects.
|
|
98
|
+
max_metadata_bytes: Maximum release-metadata response size.
|
|
94
99
|
"""
|
|
95
100
|
import json
|
|
96
101
|
import urllib.error
|
|
@@ -149,13 +154,33 @@ def resolve_github_release_asset_api_url(
|
|
|
149
154
|
release_url = f"{api_base}/repos/{owner}/{repo}/releases/tags/{encoded_tag}"
|
|
150
155
|
|
|
151
156
|
try:
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
157
|
+
open_kwargs = {"timeout": timeout}
|
|
158
|
+
if redirect_validator is not None:
|
|
159
|
+
open_kwargs["redirect_validator"] = redirect_validator
|
|
160
|
+
with open_url_fn(release_url, **open_kwargs) as response:
|
|
161
|
+
raw_release_data = response.read(max_metadata_bytes + 1)
|
|
162
|
+
if len(raw_release_data) > max_metadata_bytes:
|
|
163
|
+
raise ValueError("GitHub release metadata exceeds size limit")
|
|
164
|
+
release_data = json.loads(raw_release_data)
|
|
165
|
+
except (
|
|
166
|
+
urllib.error.URLError,
|
|
167
|
+
json.JSONDecodeError,
|
|
168
|
+
TypeError,
|
|
169
|
+
ValueError,
|
|
170
|
+
):
|
|
155
171
|
return None
|
|
156
172
|
|
|
157
|
-
|
|
158
|
-
|
|
173
|
+
if not isinstance(release_data, dict):
|
|
174
|
+
return None
|
|
175
|
+
assets = release_data.get("assets", [])
|
|
176
|
+
if not isinstance(assets, list):
|
|
177
|
+
return None
|
|
178
|
+
for asset in assets:
|
|
179
|
+
if (
|
|
180
|
+
isinstance(asset, dict)
|
|
181
|
+
and asset.get("name") == asset_name
|
|
182
|
+
and asset.get("url")
|
|
183
|
+
):
|
|
159
184
|
return str(asset["url"])
|
|
160
185
|
|
|
161
186
|
return None
|
|
@@ -14,7 +14,7 @@ def save_init_options(project_path: Path, options: dict[str, Any]) -> None:
|
|
|
14
14
|
dest = project_path / INIT_OPTIONS_FILE
|
|
15
15
|
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
16
16
|
dest.write_text(
|
|
17
|
-
json.dumps(options, indent=2, sort_keys=True, ensure_ascii=False),
|
|
17
|
+
json.dumps(options, indent=2, sort_keys=True, ensure_ascii=False) + "\n",
|
|
18
18
|
encoding="utf-8",
|
|
19
19
|
)
|
|
20
20
|
|
|
@@ -10,6 +10,8 @@ from __future__ import annotations
|
|
|
10
10
|
import json
|
|
11
11
|
import os
|
|
12
12
|
import re
|
|
13
|
+
import stat
|
|
14
|
+
import tempfile
|
|
13
15
|
from pathlib import Path, PurePosixPath
|
|
14
16
|
from typing import Any
|
|
15
17
|
|
|
@@ -87,17 +89,63 @@ def loads_json(text: str, *, origin: str = "<string>") -> Any:
|
|
|
87
89
|
|
|
88
90
|
|
|
89
91
|
def dump_json(path: Path, data: Any, *, within: Path | None = None) -> Path:
|
|
90
|
-
"""
|
|
92
|
+
"""Atomically write pretty JSON to *path* (optionally confined to *within*)."""
|
|
91
93
|
path = Path(path)
|
|
92
94
|
if within is not None:
|
|
93
95
|
path = ensure_within(within, path)
|
|
96
|
+
fd = -1
|
|
97
|
+
temp_path: Path | None = None
|
|
94
98
|
try:
|
|
95
99
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
96
|
-
|
|
100
|
+
fd, temp_name = tempfile.mkstemp(
|
|
101
|
+
dir=path.parent,
|
|
102
|
+
prefix=f".{path.name}.",
|
|
103
|
+
suffix=".tmp",
|
|
104
|
+
)
|
|
105
|
+
temp_path = Path(temp_name)
|
|
106
|
+
with os.fdopen(os.dup(fd), "w", encoding="utf-8") as handle:
|
|
97
107
|
json.dump(data, handle, indent=2, sort_keys=False)
|
|
98
108
|
handle.write("\n")
|
|
109
|
+
|
|
110
|
+
try:
|
|
111
|
+
if path.exists():
|
|
112
|
+
existing = path.stat(follow_symlinks=False)
|
|
113
|
+
if stat.S_ISREG(existing.st_mode) and hasattr(os, "fchmod"):
|
|
114
|
+
os.fchmod(fd, stat.S_IMODE(existing.st_mode))
|
|
115
|
+
if stat.S_ISREG(existing.st_mode) and hasattr(os, "fchown"):
|
|
116
|
+
try:
|
|
117
|
+
os.fchown(fd, existing.st_uid, existing.st_gid)
|
|
118
|
+
except PermissionError:
|
|
119
|
+
pass
|
|
120
|
+
except OSError:
|
|
121
|
+
pass
|
|
122
|
+
|
|
123
|
+
staged = os.stat(temp_path, follow_symlinks=False)
|
|
124
|
+
opened = os.fstat(fd)
|
|
125
|
+
if (
|
|
126
|
+
not stat.S_ISREG(staged.st_mode)
|
|
127
|
+
or staged.st_dev != opened.st_dev
|
|
128
|
+
or staged.st_ino != opened.st_ino
|
|
129
|
+
):
|
|
130
|
+
raise OSError("staged JSON file changed before commit")
|
|
131
|
+
|
|
132
|
+
os.close(fd)
|
|
133
|
+
fd = -1
|
|
134
|
+
os.replace(temp_path, path)
|
|
135
|
+
temp_path = None
|
|
99
136
|
except OSError as exc:
|
|
100
137
|
raise BundlerError(f"Could not write {path}: {exc}") from exc
|
|
138
|
+
finally:
|
|
139
|
+
if fd >= 0:
|
|
140
|
+
try:
|
|
141
|
+
os.close(fd)
|
|
142
|
+
except OSError:
|
|
143
|
+
pass
|
|
144
|
+
if temp_path is not None:
|
|
145
|
+
try:
|
|
146
|
+
temp_path.unlink(missing_ok=True)
|
|
147
|
+
except OSError:
|
|
148
|
+
pass
|
|
101
149
|
return path
|
|
102
150
|
|
|
103
151
|
|
|
@@ -187,19 +187,41 @@ def remove_bundle(
|
|
|
187
187
|
|
|
188
188
|
still_needed = components_still_needed(records, exclude_bundle_id=bundle_id)
|
|
189
189
|
result = InstallResult(bundle_id=bundle_id)
|
|
190
|
+
remove_attempted = False
|
|
190
191
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
installer.
|
|
198
|
-
|
|
192
|
+
try:
|
|
193
|
+
for component in target.contributed_components:
|
|
194
|
+
key = (component.kind, component.id)
|
|
195
|
+
if key in still_needed:
|
|
196
|
+
result.skipped.append(component)
|
|
197
|
+
continue
|
|
198
|
+
if installer.is_installed(project_root, component):
|
|
199
|
+
remove_attempted = True
|
|
200
|
+
installer.remove(project_root, component)
|
|
201
|
+
result.uninstalled.append(component)
|
|
202
|
+
save_records(project_root, remove_record(records, bundle_id))
|
|
203
|
+
except Exception as exc: # noqa: BLE001
|
|
204
|
+
if result.uninstalled:
|
|
205
|
+
detail = (
|
|
206
|
+
f"{len(result.uninstalled)} component(s) were already removed "
|
|
207
|
+
"before this failure; the bundle record was left unchanged, "
|
|
208
|
+
"so the project may be partially uninstalled."
|
|
209
|
+
)
|
|
210
|
+
elif remove_attempted:
|
|
211
|
+
detail = (
|
|
212
|
+
"No components were removed, but the failing component may "
|
|
213
|
+
"have made partial changes before raising, so the project "
|
|
214
|
+
"may be partially uninstalled."
|
|
215
|
+
)
|
|
199
216
|
else:
|
|
200
|
-
|
|
217
|
+
detail = (
|
|
218
|
+
"No components were removed and no removal was attempted; "
|
|
219
|
+
"the bundle record was left unchanged."
|
|
220
|
+
)
|
|
221
|
+
raise BundlerError(
|
|
222
|
+
f"Failed to remove bundle '{bundle_id}': {exc}. {detail}"
|
|
223
|
+
) from exc
|
|
201
224
|
|
|
202
|
-
save_records(project_root, remove_record(records, bundle_id))
|
|
203
225
|
return result
|
|
204
226
|
|
|
205
227
|
|
|
@@ -2737,6 +2737,36 @@ class ConfigManager:
|
|
|
2737
2737
|
config_file = self.extension_dir / "local-config.yml"
|
|
2738
2738
|
return self._load_yaml_config(config_file)
|
|
2739
2739
|
|
|
2740
|
+
def _sibling_extension_ids(self) -> list[str]:
|
|
2741
|
+
"""Return IDs of other extensions installed alongside this one.
|
|
2742
|
+
|
|
2743
|
+
Sourced from ``ExtensionRegistry`` (``.specify/extensions/.registry``)
|
|
2744
|
+
rather than a directory scan: ``ExtensionManager.remove(...,
|
|
2745
|
+
keep_config=True)`` deliberately preserves the extension directory
|
|
2746
|
+
while dropping the registry entry, so a directory scan would treat
|
|
2747
|
+
that config-only leftover as an installed sibling and keep silently
|
|
2748
|
+
absorbing its ``SPECKIT_<sibling>_*`` env vars into no one. The
|
|
2749
|
+
registry is the source of truth for "installed".
|
|
2750
|
+
|
|
2751
|
+
Returns an empty list if the registry is missing or corrupted
|
|
2752
|
+
(fresh project, ad-hoc test harness) so ``_get_env_config`` degrades
|
|
2753
|
+
to its pre-fix behaviour rather than crashing. ``UnicodeError`` is
|
|
2754
|
+
caught alongside ``OSError`` because ``ExtensionRegistry._load()``
|
|
2755
|
+
opens the file in text mode and only handles ``JSONDecodeError`` /
|
|
2756
|
+
``FileNotFoundError``, so a registry file with non-UTF-8 bytes would
|
|
2757
|
+
otherwise surface a ``UnicodeDecodeError`` here and break *every*
|
|
2758
|
+
config read instead of degrading gracefully.
|
|
2759
|
+
|
|
2760
|
+
Used by ``_get_env_config`` to detect env vars whose remainder claims
|
|
2761
|
+
a longer, sibling-owned prefix (e.g. ``SPECKIT_GIT_HOOKS_URL`` is
|
|
2762
|
+
owned by ``git-hooks`` when it is co-installed with ``git``).
|
|
2763
|
+
"""
|
|
2764
|
+
extensions_dir = self.project_root / ".specify" / "extensions"
|
|
2765
|
+
try:
|
|
2766
|
+
return list(ExtensionRegistry(extensions_dir).keys())
|
|
2767
|
+
except (OSError, UnicodeError):
|
|
2768
|
+
return []
|
|
2769
|
+
|
|
2740
2770
|
def _get_env_config(self) -> Dict[str, Any]:
|
|
2741
2771
|
"""Get configuration from environment variables.
|
|
2742
2772
|
|
|
@@ -2756,15 +2786,49 @@ class ConfigManager:
|
|
|
2756
2786
|
ext_id_upper = self.extension_id.replace("-", "_").upper()
|
|
2757
2787
|
prefix = f"SPECKIT_{ext_id_upper}_"
|
|
2758
2788
|
|
|
2789
|
+
# Cross-extension prefix collision: because ``_`` doubles as both the
|
|
2790
|
+
# separator between the extension ID and the config path *and* the
|
|
2791
|
+
# substitute for ``-`` inside an extension ID, an env var like
|
|
2792
|
+
# ``SPECKIT_GIT_HOOKS_URL`` begins with *both* the ``SPECKIT_GIT_``
|
|
2793
|
+
# prefix of the ``git`` extension and the ``SPECKIT_GIT_HOOKS_`` prefix
|
|
2794
|
+
# of a co-installed ``git-hooks`` extension. It logically belongs to
|
|
2795
|
+
# the extension whose normalized ID is the longer, more specific match
|
|
2796
|
+
# — otherwise config intended for one extension silently surfaces
|
|
2797
|
+
# inside another and can drive hooks that only inspect
|
|
2798
|
+
# ``config.<field> is set``. Build the list of sibling-owned
|
|
2799
|
+
# remainder-prefixes here so a later env var can be skipped if it
|
|
2800
|
+
# matches one.
|
|
2801
|
+
sibling_prefixes: list[str] = []
|
|
2802
|
+
for sibling_id in self._sibling_extension_ids():
|
|
2803
|
+
if sibling_id == self.extension_id:
|
|
2804
|
+
continue
|
|
2805
|
+
sib_upper = sibling_id.replace("-", "_").upper()
|
|
2806
|
+
# A sibling collides only when its normalized ID *extends* our own
|
|
2807
|
+
# (i.e. starts with ``<US>_``). ``git`` vs ``not-git`` is not a
|
|
2808
|
+
# collision; ``git`` vs ``git-hooks`` is.
|
|
2809
|
+
if sib_upper.startswith(ext_id_upper + "_"):
|
|
2810
|
+
# The portion of the env-var *remainder* the sibling claims,
|
|
2811
|
+
# including the trailing ``_`` so a shorter ID that shares a
|
|
2812
|
+
# non-boundary prefix cannot false-positive (e.g. sibling
|
|
2813
|
+
# ``hook`` would not eat env vars under key ``hooks``).
|
|
2814
|
+
sibling_prefixes.append(sib_upper[len(ext_id_upper) + 1 :] + "_")
|
|
2815
|
+
|
|
2759
2816
|
for key, value in os.environ.items():
|
|
2760
2817
|
if not key.startswith(prefix):
|
|
2761
2818
|
continue
|
|
2762
2819
|
|
|
2820
|
+
remainder = key[len(prefix) :]
|
|
2821
|
+
# Skip when a longer sibling ID claims this var — see the block
|
|
2822
|
+
# above. Keeps ``SPECKIT_GIT_HOOKS_URL`` out of the ``git``
|
|
2823
|
+
# extension's config when ``git-hooks`` is co-installed.
|
|
2824
|
+
if any(remainder.startswith(sp) for sp in sibling_prefixes):
|
|
2825
|
+
continue
|
|
2826
|
+
|
|
2763
2827
|
# Remove prefix and split into parts. Drop empty components from a
|
|
2764
2828
|
# malformed name (e.g. ``SPECKIT_<EXT>_`` with no key, or
|
|
2765
2829
|
# consecutive underscores ``SPECKIT_X__Y``) so we never create an
|
|
2766
2830
|
# entry under an empty key.
|
|
2767
|
-
config_path = [p for p in
|
|
2831
|
+
config_path = [p for p in remainder.lower().split("_") if p]
|
|
2768
2832
|
if not config_path:
|
|
2769
2833
|
continue
|
|
2770
2834
|
|
|
@@ -1122,6 +1122,17 @@ class TomlIntegration(IntegrationBase):
|
|
|
1122
1122
|
# YamlIntegration — YAML-format agents (Goose)
|
|
1123
1123
|
# ---------------------------------------------------------------------------
|
|
1124
1124
|
|
|
1125
|
+
# Characters a YAML literal block scalar cannot carry: C0 controls other
|
|
1126
|
+
# than tab/LF (a bare CR acts as a line break inside the scalar), DEL, the
|
|
1127
|
+
# C1 range, lone UTF-16 surrogates, and the non-characters U+FFFE/U+FFFF.
|
|
1128
|
+
# NEL (U+0085) is YAML-printable but, like LS/PS (U+2028/U+2029), YAML 1.1
|
|
1129
|
+
# treats it as a line break, which corrupts the block scalar's structure
|
|
1130
|
+
# just the same, so all three are included.
|
|
1131
|
+
_YAML_BLOCK_SCALAR_UNSAFE = re.compile(
|
|
1132
|
+
r"[\x00-\x08\x0b-\x1f\x7f-\x9f\u2028\u2029\ud800-\udfff\ufffe\uffff]"
|
|
1133
|
+
)
|
|
1134
|
+
|
|
1135
|
+
|
|
1125
1136
|
class YamlIntegration(IntegrationBase):
|
|
1126
1137
|
"""Concrete base for integrations that use YAML recipe format.
|
|
1127
1138
|
|
|
@@ -1227,9 +1238,9 @@ class YamlIntegration(IntegrationBase):
|
|
|
1227
1238
|
def _render_yaml(cls, title: str, description: str, body: str, source_id: str) -> str:
|
|
1228
1239
|
"""Render a YAML recipe file from title, description, and body.
|
|
1229
1240
|
|
|
1230
|
-
Produces a Goose-compatible recipe with a literal block scalar
|
|
1231
|
-
|
|
1232
|
-
|
|
1241
|
+
Produces a Goose-compatible recipe with a literal block scalar for
|
|
1242
|
+
normal prompt content, or an escaped quoted scalar when control
|
|
1243
|
+
characters require it. Uses ``yaml.safe_dump()`` for the header fields.
|
|
1233
1244
|
"""
|
|
1234
1245
|
header = cls._build_yaml_header(title, description)
|
|
1235
1246
|
|
|
@@ -1240,6 +1251,23 @@ class YamlIntegration(IntegrationBase):
|
|
|
1240
1251
|
default_flow_style=False,
|
|
1241
1252
|
).strip()
|
|
1242
1253
|
|
|
1254
|
+
# YAML forbids C0 control characters (except tab and newline) and
|
|
1255
|
+
# DEL in every scalar form, and a bare CR acts as a line break
|
|
1256
|
+
# inside a block scalar. A literal block scalar emits such bytes
|
|
1257
|
+
# verbatim, producing a recipe the YAML parser rejects, so fall
|
|
1258
|
+
# back to an escaped double-quoted scalar for those bodies.
|
|
1259
|
+
if _YAML_BLOCK_SCALAR_UNSAFE.search(body):
|
|
1260
|
+
prompt_yaml = yaml.safe_dump(
|
|
1261
|
+
{"prompt": body}, allow_unicode=True, default_style='"', width=sys.maxsize
|
|
1262
|
+
).strip()
|
|
1263
|
+
lines = [
|
|
1264
|
+
header_yaml,
|
|
1265
|
+
prompt_yaml,
|
|
1266
|
+
"",
|
|
1267
|
+
f"# Source: {source_id}",
|
|
1268
|
+
]
|
|
1269
|
+
return "\n".join(lines) + "\n"
|
|
1270
|
+
|
|
1243
1271
|
# Indent the body for YAML block scalar. Use an explicit indentation
|
|
1244
1272
|
# indicator ("|2") rather than a bare "|": YAML infers a plain block
|
|
1245
1273
|
# scalar's indentation from its first non-empty line, so a body whose
|