specify-cli 0.15.1__tar.gz → 0.15.2__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.15.1 → specify_cli-0.15.2}/CHANGELOG.md +25 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/PKG-INFO +1 -1
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/community/extensions.md +1 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/reference/core.md +2 -1
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/reference/workflows.md +13 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/catalog.community.json +36 -1
- {specify_cli-0.15.1 → specify_cli-0.15.2}/pyproject.toml +1 -1
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/__init__.py +2 -0
- specify_cli-0.15.2/src/specify_cli/_agent_config.py +56 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/agents.py +1 -1
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/services/adapters.py +3 -3
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/services/packager.py +5 -3
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/commands/bundle/__init__.py +4 -2
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/commands/init.py +220 -5
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/events.py +1 -1
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/extensions/__init__.py +177 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/extensions/_commands.py +194 -128
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/kimi/__init__.py +1 -1
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/presets/__init__.py +88 -7
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/catalog.py +2 -2
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/engine.py +47 -18
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/steps/fan_in/__init__.py +24 -2
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/steps/gate/__init__.py +25 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/steps/init/__init__.py +18 -6
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integration/test_bundler_init_install.py +14 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_cli.py +338 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_events.py +7 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_kimi.py +18 -0
- specify_cli-0.15.2/tests/test_commands_package.py +100 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_extensions.py +407 -4
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_post_process.py +26 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_presets.py +230 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_workflows.py +335 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/unit/test_bundler_adapters.py +12 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/unit/test_bundler_packager.py +26 -0
- specify_cli-0.15.1/src/specify_cli/_agent_config.py +0 -24
- specify_cli-0.15.1/tests/test_commands_package.py +0 -52
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.devcontainer/devcontainer.json +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.devcontainer/post-create.sh +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.editorconfig +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.gitattributes +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/CODEOWNERS +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/ISSUE_TEMPLATE/agent_request.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/ISSUE_TEMPLATE/bundle_submission.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/ISSUE_TEMPLATE/extension_submission.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/ISSUE_TEMPLATE/preset_submission.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/aw/actions-lock.json +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/dependabot.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/scripts/check_security_requirements.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/security-audit-requirements.txt +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/skills/add-community-extension/SKILL.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/RELEASE-PROCESS.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/add-community-bundle.lock.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/add-community-bundle.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/add-community-extension.lock.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/add-community-extension.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/add-community-preset.lock.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/add-community-preset.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/bug-assess.lock.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/bug-assess.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/bug-fix.lock.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/bug-fix.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/bug-test.lock.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/bug-test.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/catalog-assign.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/codeql.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/docs.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/lint.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/publish-pypi.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/release-trigger.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/release.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/security.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/stale.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.github/workflows/test.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.gitignore +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.markdownlint-cli2.jsonc +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.pre-commit-config.yaml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/.zenodo.json +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/AGENTS.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/CITATION.cff +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/CODE_OF_CONDUCT.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/CONTRIBUTING.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/DEVELOPMENT.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/LICENSE +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/README.zh-CN.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/SECURITY.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/SUPPORT.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/bundles/catalog.community.json +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/.gitignore +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/community/bundles.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/community/friends.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/community/overview.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/community/presets.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/community/walkthroughs.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/concepts/complex-features.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/concepts/sdd.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/concepts/spec-of-specs.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/concepts/spec-persistence.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/docfx.json +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/guides/evolving-specs.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/guides/monorepo.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/index.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/install/air-gapped.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/install/one-time.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/install/pipx.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/install/pypi.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/install/uv.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/installation.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/local-development.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/quickstart.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/reference/agentic-bugfix.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/reference/agentic-sdd.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/reference/authentication.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/reference/bundles.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/reference/extensions.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/reference/integrations.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/reference/overview.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/reference/presets.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/template/public/main.css +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/toc.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/docs/upgrade.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/examples/bundles/business-analyst/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/examples/bundles/business-analyst/bundle.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/examples/bundles/developer/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/examples/bundles/developer/bundle.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/examples/bundles/product-manager/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/examples/bundles/product-manager/bundle.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/examples/bundles/security-researcher/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/examples/bundles/security-researcher/bundle.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/EXTENSION-API-REFERENCE.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/EXTENSION-DEVELOPMENT-GUIDE.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/EXTENSION-PUBLISHING-GUIDE.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/EXTENSION-USER-GUIDE.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/RFC-EXTENSION-SYSTEM.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/agent-context/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/agent-context/agent-context-config.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/agent-context/agent-context-defaults.json +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/agent-context/commands/speckit.agent-context.update.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/agent-context/extension.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/agent-context/scripts/bash/update-agent-context.sh +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/agent-context/scripts/powershell/update-agent-context.ps1 +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/agent-context/scripts/python/update_agent_context.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/assess/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/assess/commands/speckit.assess.decide.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/assess/commands/speckit.assess.define.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/assess/commands/speckit.assess.intake.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/assess/commands/speckit.assess.research.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/assess/commands/speckit.assess.shape.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/assess/extension.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/bug/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/bug/commands/speckit.bug.assess.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/bug/commands/speckit.bug.fix.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/bug/commands/speckit.bug.test.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/bug/extension.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/catalog.json +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/commands/speckit.git.commit.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/commands/speckit.git.feature.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/commands/speckit.git.initialize.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/commands/speckit.git.remote.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/commands/speckit.git.validate.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/config-template.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/extension.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/git-config.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/scripts/bash/auto-commit.sh +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/scripts/bash/create-new-feature-branch.sh +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/scripts/bash/git-common.sh +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/scripts/bash/initialize-repo.sh +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/scripts/powershell/auto-commit.ps1 +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/scripts/powershell/create-new-feature-branch.ps1 +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/scripts/powershell/git-common.ps1 +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/scripts/powershell/initialize-repo.ps1 +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/scripts/python/auto_commit.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/scripts/python/create_new_feature_branch.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/scripts/python/git_common.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/git/scripts/python/initialize_repo.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/selftest/commands/selftest.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/selftest/extension.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/template/.gitignore +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/template/CHANGELOG.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/template/EXAMPLE-README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/template/LICENSE +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/template/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/template/commands/example.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/template/config-template.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/extensions/template/extension.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/integrations/CONTRIBUTING.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/integrations/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/integrations/catalog.community.json +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/integrations/catalog.json +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/media/bootstrap-claude-code.gif +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/media/logo_large.webp +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/media/logo_small.webp +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/media/spec-kit-video-header.jpg +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/media/specify_cli.gif +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/newsletters/2026-April.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/newsletters/2026-February.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/newsletters/2026-June.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/newsletters/2026-March.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/newsletters/2026-May.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/ARCHITECTURE.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/PUBLISHING.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/catalog.community.json +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/catalog.json +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/constitution-sync/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/constitution-sync/commands/speckit.constitution.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/constitution-sync/preset.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/lean/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/lean/commands/speckit.constitution.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/lean/commands/speckit.implement.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/lean/commands/speckit.plan.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/lean/commands/speckit.specify.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/lean/commands/speckit.tasks.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/lean/preset.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/scaffold/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/scaffold/commands/speckit.myext.myextcmd.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/scaffold/commands/speckit.specify.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/scaffold/preset.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/scaffold/templates/myext-template.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/scaffold/templates/spec-template.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/self-test/commands/speckit.specify.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/self-test/commands/speckit.wrap-test.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/self-test/preset.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/self-test/templates/checklist-template.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/self-test/templates/constitution-template.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/self-test/templates/plan-template.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/self-test/templates/spec-template.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/presets/self-test/templates/tasks-template.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/scripts/bash/check-prerequisites.sh +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/scripts/bash/common.sh +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/scripts/bash/create-new-feature.sh +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/scripts/bash/setup-plan.sh +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/scripts/bash/setup-tasks.sh +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/scripts/powershell/check-prerequisites.ps1 +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/scripts/powershell/common.ps1 +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/scripts/powershell/create-new-feature.ps1 +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/scripts/powershell/setup-plan.ps1 +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/scripts/powershell/setup-tasks.ps1 +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/scripts/python/check_prerequisites.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/scripts/python/common.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/scripts/python/create_new_feature.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/scripts/python/setup_plan.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/scripts/python/setup_tasks.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/spec-driven.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/spec-kit.code-workspace +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/_assets.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/_console.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/_download_security.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/_github_http.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/_init_options.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/_invocation_style.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/_project.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/_toml_string.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/_utils.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/_version.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/authentication/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/authentication/azure_devops.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/authentication/base.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/authentication/config.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/authentication/github.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/authentication/http.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/commands_impl/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/commands_impl/catalog_config.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/lib/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/lib/project.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/lib/versioning.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/lib/yamlio.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/models/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/models/catalog.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/models/manifest.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/models/records.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/services/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/services/catalog_stack.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/services/conflict.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/services/installer.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/services/primitives.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/services/references.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/services/resolver.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/bundler/services/validator.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/catalogs.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/commands/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/commands/event.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integration_runtime.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integration_scaffold.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integration_state.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integration_status.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/_commands.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/_helpers.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/_install_commands.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/_migrate_commands.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/_query_commands.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/_scaffold_commands.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/agy/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/alquimia/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/amp/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/auggie/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/base.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/bob/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/catalog.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/claude/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/cline/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/codebuddy/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/codex/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/copilot/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/cursor_agent/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/devin/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/droid/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/firebender/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/forge/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/gemini/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/generic/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/goose/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/grok/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/hermes/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/junie/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/kilocode/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/kiro_cli/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/lingma/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/manifest.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/omp/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/opencode/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/pi/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/qodercli/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/qwen/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/rovodev/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/shai/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/tabnine/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/trae/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/vibe/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/zcode/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/integrations/zed/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/presets/_commands.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/shared_infra.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/_commands.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/base.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/expressions.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/overlays/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/overlays/_commands.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/overlays/composer.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/overlays/layer_sources.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/overlays/merge.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/overlays/schema.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/steps/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/steps/command/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/steps/do_while/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/steps/fan_out/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/steps/if_then/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/steps/prompt/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/steps/shell/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/steps/switch/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/src/specify_cli/workflows/steps/while_loop/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/templates/checklist-template.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/templates/commands/analyze.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/templates/commands/checklist.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/templates/commands/clarify.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/templates/commands/constitution.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/templates/commands/converge.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/templates/commands/implement.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/templates/commands/plan.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/templates/commands/specify.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/templates/commands/tasks.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/templates/commands/taskstoissues.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/templates/constitution-template.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/templates/plan-template.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/templates/spec-template.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/templates/tasks-template.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/templates/vscode-settings.json +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/auth_helpers.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/bundler_helpers.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/conftest.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/contract/test_bundle_cli.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/contract/test_catalog_schema.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/contract/test_manifest_schema.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/contract/test_wheel_bundled_presets.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/contract/test_wheel_core_pack_scripts.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/extensions/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/extensions/assess/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/extensions/assess/test_assess_extension.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/extensions/bug/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/extensions/bug/test_bug_extension.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/extensions/git/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/extensions/git/test_git_extension.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/extensions/git/test_git_extension_python_parity.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/extensions/test_agent_context_cli_free.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/extensions/test_extension_agent_context.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/extensions/test_update_agent_context_feature_json.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/extensions/test_update_agent_context_python_parity.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/hooks/TESTING.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/hooks/plan.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/hooks/spec.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/hooks/tasks.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/http_helpers.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integration/test_bundler_catalog_stack.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integration/test_bundler_install_flow.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integration/test_bundler_local_install.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integration/test_bundler_offline.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integration/test_bundler_security_paths.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/__init__.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/conftest.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_base.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_extra_args.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_home_isolation.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_agy.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_alquimia.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_amp.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_auggie.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_base_markdown.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_base_skills.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_base_toml.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_base_yaml.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_bob.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_catalog.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_claude.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_cline.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_codebuddy.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_codex.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_copilot.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_cursor_agent.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_devin.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_droid.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_firebender.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_forge.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_gemini.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_generic.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_goose.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_grok.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_hermes.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_junie.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_kilocode.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_kiro_cli.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_lingma.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_omp.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_opencode.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_pi.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_qodercli.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_qwen.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_rovodev.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_scaffold.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_shai.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_state.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_subcommand.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_tabnine.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_trae.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_vibe.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_zcode.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_integration_zed.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_manifest.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_registry.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/integrations/test_skill_frontmatter_quoting.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/parity_helpers.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/self_upgrade_helpers.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_agent_config_consistency.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_authentication.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_branch_numbering.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_check_prerequisites_paths_only.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_check_prerequisites_python_parity.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_check_tool.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_cli_version.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_command_template_py_scripts.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_console_imports.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_create_new_feature_python_parity.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_download_security.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_extension_add_path_traversal.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_extension_registration.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_extension_skills.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_extension_update_hardening.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_github_http.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_github_workflows.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_init_dir.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_init_dir_cli.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_live_transient_windows.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_merge.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_ps1_encoding.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_registrar_path_traversal.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_security_workflow.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_self_upgrade_detection.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_self_upgrade_execution.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_self_upgrade_guidance.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_self_upgrade_verification.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_setup_plan_feature_json.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_setup_plan_no_overwrite.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_setup_plan_python_parity.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_setup_tasks.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_setup_tasks_python_parity.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_shared_infra_integrity.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_skill_placeholder_py.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_specify_template_numbering.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_timestamp_branches.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_upgrade.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_utils.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_utils_assets_imports.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_version_imports.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/test_workflow_run_without_project.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/unit/test_bundle_download_url.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/unit/test_bundler_catalog_config.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/unit/test_bundler_conflict.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/unit/test_bundler_primitives.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/unit/test_bundler_records.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/unit/test_bundler_references.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/unit/test_bundler_resolver.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/unit/test_bundler_validator.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/unit/test_bundler_versioning.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/unit/test_bundler_yamlio.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/workflows/conftest.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/workflows/test_overlay_commands.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/workflows/test_overlay_composer.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/workflows/test_overlay_layer_sources.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/workflows/test_overlay_merge.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/workflows/test_overlay_schema.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/workflows/test_overlay_security.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/tests/workflows/test_resolver_integration.py +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/workflows/ARCHITECTURE.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/workflows/PUBLISHING.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/workflows/README.md +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/workflows/catalog.community.json +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/workflows/catalog.json +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/workflows/speckit/workflow.yml +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/workflows/step-catalog.community.json +0 -0
- {specify_cli-0.15.1 → specify_cli-0.15.2}/workflows/step-catalog.json +0 -0
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
<!-- insert new changelog below this comment -->
|
|
4
4
|
|
|
5
|
+
## [0.15.2] - 2026-08-03
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- fix(presets): restore core skills instead of deleting them on preset remove (#3929)
|
|
10
|
+
- fix(manifests): reject non-string metadata instead of crashing on it (#3943)
|
|
11
|
+
- fix: narrow bare except Exception in invoke separator resolution (#3856)
|
|
12
|
+
- fix(workflows): keep the init step's documented ignore_agent_tools default on an explicit null (#3889)
|
|
13
|
+
- fix(kimi): preserve non-UTF-8 user skills (#3895)
|
|
14
|
+
- fix(presets): tolerate non-UTF-8 legacy commands (#3896)
|
|
15
|
+
- feat: allow overriding default init integration via SPECKIT_INTEGRATION_DEFAULT (#3952)
|
|
16
|
+
- Add adrkit extension to community catalog (#3947)
|
|
17
|
+
- feat(extensions): scaffold config templates on extension add/enable (#2000)
|
|
18
|
+
- fix(events): skip non-UTF-8 extension manifests (#3900)
|
|
19
|
+
- fix(workflows): fail a gate whose on_reject is not abort/skip/retry (#3888)
|
|
20
|
+
- fix(presets): validate required manifest mappings (#3898)
|
|
21
|
+
- fix: eliminate TOCTOU race in zip packaging (#3855)
|
|
22
|
+
- fix(workflows): fail a fan-in step whose output is not a mapping (#3887)
|
|
23
|
+
- fix(workflows): refetch non-UTF-8 catalog caches (#3901)
|
|
24
|
+
- fix(bundler): wrap local catalog decode failures (#3902)
|
|
25
|
+
- Add `--extension` flag to `specify init` for opting into extensions at init time (#3914)
|
|
26
|
+
- fix: bound response reads in extension catalog and download (#3775)
|
|
27
|
+
- fix(workflows): reject a retry gate whose verdict enum forbids the reset value (#3912)
|
|
28
|
+
- chore: release 0.15.1, begin 0.15.2.dev0 development (#3913)
|
|
29
|
+
|
|
5
30
|
## [0.15.1] - 2026-07-31
|
|
6
31
|
|
|
7
32
|
### Changed
|
|
@@ -25,6 +25,7 @@ The following community-contributed extensions are available in [`catalog.commun
|
|
|
25
25
|
|
|
26
26
|
| Extension | Purpose | Category | Effect | URL |
|
|
27
27
|
|-----------|---------|----------|--------|-----|
|
|
28
|
+
| adrkit — decision memory for spec-driven development | Pulls the decisions governing this work into agent context, checks produced plans against them, and drafts an ADR from a plan artifact | `process` | Read+Write | [adrkit](https://github.com/mbeacom/adrkit) |
|
|
28
29
|
| Agent Assign | Assign specialized Claude Code agents to spec-kit tasks for targeted execution | `process` | Read+Write | [spec-kit-agent-assign](https://github.com/xymelon/spec-kit-agent-assign) |
|
|
29
30
|
| Agent Governance | Generate agent-platform repository governance files from Spec Kit metadata | `process` | Read+Write | [spec-kit-agent-governance](https://github.com/bigsmartben/spec-kit-agent-governance) |
|
|
30
31
|
| AI-Driven Engineering (AIDE) | A structured 7-step workflow for building new projects from scratch with AI assistants — from vision through implementation | `process` | Read+Write | [aide](https://github.com/mnriem/spec-kit-extensions/tree/main/aide) |
|
|
@@ -25,7 +25,7 @@ Creates a new Spec Kit project with the necessary directory structure, templates
|
|
|
25
25
|
|
|
26
26
|
Use `<project_name>` to create a new directory, or `--here` (or `.`) to initialize in the current directory. If the directory already has files, use `--force` to merge without confirmation.
|
|
27
27
|
|
|
28
|
-
When `--integration` is omitted, interactive terminals prompt you to choose an integration. Non-interactive sessions, such as CI or piped runs, default to GitHub Copilot; pass `--integration <key>` to choose a different integration explicitly.
|
|
28
|
+
When `--integration` is omitted, interactive terminals prompt you to choose an integration. Non-interactive sessions, such as CI or piped runs, default to GitHub Copilot; pass `--integration <key>` to choose a different integration explicitly, or set `SPECKIT_INTEGRATION_DEFAULT` to change the fallback (see [Environment Variables](#environment-variables)).
|
|
29
29
|
|
|
30
30
|
### Examples
|
|
31
31
|
|
|
@@ -50,6 +50,7 @@ specify init my-project --integration copilot --preset compliance
|
|
|
50
50
|
|
|
51
51
|
| Variable | Description |
|
|
52
52
|
| ----------------- | ------------------------------------------------------------------------ |
|
|
53
|
+
| `SPECKIT_INTEGRATION_DEFAULT` | Override the fallback integration used by `specify init` when `--integration` is omitted (interactive prompt default and non-interactive fallback). Set it to any registered integration key (e.g. `gemini`, `claude`). An unrecognized value is ignored with a warning and the built-in default (`copilot`) is used. An explicit `--integration <key>` always takes precedence. |
|
|
53
54
|
| `SPECIFY_INIT_DIR` | Target a member project from outside its directory (e.g. a monorepo root) without `cd`, for non-interactive / CI use. Set it to the **project root** — the directory *containing* `.specify/` (relative paths resolve against the current directory). The path must exist and contain `.specify/`, otherwise the command errors and does **not** fall back to the current directory. Resolved once in the core root helper (`get_repo_root` in Bash, `Get-RepoRoot` in PowerShell), so it is honored by the core feature scripts (`/speckit.plan`, `/speckit.tasks`, …) and the Git extension's feature-branch creation, which inherit it. The `specify` CLI applies the **same** validation rules to every project-scoped subcommand (`specify integration …`, `specify extension …`, `specify workflow …`, `specify preset …`, and the rest that operate on a `.specify/` project), so those can target a member project too. When unset, Bash/PowerShell helpers keep their existing upward search; the `specify` CLI keeps its project-scoped resolver cwd-only unless a command explicitly defines broader detection (for example, bundle commands). |
|
|
54
55
|
| `SPECIFY_FEATURE_DIRECTORY` | Override the active feature directory *within* the resolved project (takes precedence over `.specify/feature.json`). Relative paths resolve under the project root. Combine with `SPECIFY_INIT_DIR` to pick both the project and the feature non-interactively. |
|
|
55
56
|
| `SPECIFY_FEATURE` | Override feature detection for non-Git repositories. Set to the feature directory name (e.g., `001-photo-albums`) to work on a specific feature when not using Git branches. Must be set in the context of the agent prior to using `/speckit.plan` or follow-up commands. |
|
|
@@ -623,6 +623,19 @@ pauses: the named stored input is reset to `""`. A later resume therefore
|
|
|
623
623
|
prompts or pauses again until another verdict is supplied. Approve, abort, and
|
|
624
624
|
skip outcomes leave the input unchanged.
|
|
625
625
|
|
|
626
|
+
Because of that reset, a verdict input used with `on_reject: retry` must accept
|
|
627
|
+
`""`. If it declares an `enum`, include the empty string — otherwise the reset
|
|
628
|
+
value violates the input's own `enum` and the run can no longer be resumed with
|
|
629
|
+
any input. `specify workflow add` reports this as a validation error.
|
|
630
|
+
|
|
631
|
+
```yaml
|
|
632
|
+
inputs:
|
|
633
|
+
spec_verdict:
|
|
634
|
+
type: string
|
|
635
|
+
enum: ["", approve, reject]
|
|
636
|
+
default: ""
|
|
637
|
+
```
|
|
638
|
+
|
|
626
639
|
## FAQ
|
|
627
640
|
|
|
628
641
|
### What happens when a workflow hits a gate step?
|
|
@@ -1,8 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema_version": "1.0",
|
|
3
|
-
"updated_at": "2026-
|
|
3
|
+
"updated_at": "2026-08-03T00:00:00Z",
|
|
4
4
|
"catalog_url": "https://raw.githubusercontent.com/github/spec-kit/main/extensions/catalog.community.json",
|
|
5
5
|
"extensions": {
|
|
6
|
+
"adrkit": {
|
|
7
|
+
"name": "adrkit — decision memory for spec-driven development",
|
|
8
|
+
"id": "adrkit",
|
|
9
|
+
"description": "Pulls the decisions governing this work into agent context, checks produced plans against them, and drafts an ADR from a plan artifact.",
|
|
10
|
+
"author": "Mark Beacom (@mbeacom)",
|
|
11
|
+
"version": "0.1.2",
|
|
12
|
+
"download_url": "https://github.com/mbeacom/adrkit/releases/download/spec-kit-v0.1.2/adrkit.zip",
|
|
13
|
+
"repository": "https://github.com/mbeacom/adrkit",
|
|
14
|
+
"homepage": "https://adrkit.dev",
|
|
15
|
+
"documentation": "https://github.com/mbeacom/adrkit/blob/main/packages/adapters/spec-kit/README.md",
|
|
16
|
+
"changelog": "https://github.com/mbeacom/adrkit/blob/main/CHANGELOG.md",
|
|
17
|
+
"license": "Apache-2.0",
|
|
18
|
+
"category": "process",
|
|
19
|
+
"effect": "read-write",
|
|
20
|
+
"requires": {
|
|
21
|
+
"speckit_version": ">=0.13.0,<0.16.0",
|
|
22
|
+
"tools": [{ "name": "adr", "version": ">=0.3.0", "required": true }]
|
|
23
|
+
},
|
|
24
|
+
"provides": {
|
|
25
|
+
"commands": 3,
|
|
26
|
+
"hooks": 1
|
|
27
|
+
},
|
|
28
|
+
"tags": [
|
|
29
|
+
"adr",
|
|
30
|
+
"governance",
|
|
31
|
+
"decision-records",
|
|
32
|
+
"architecture",
|
|
33
|
+
"compliance"
|
|
34
|
+
],
|
|
35
|
+
"verified": false,
|
|
36
|
+
"downloads": 0,
|
|
37
|
+
"stars": 0,
|
|
38
|
+
"created_at": "2026-08-03T00:00:00Z",
|
|
39
|
+
"updated_at": "2026-08-03T00:00:00Z"
|
|
40
|
+
},
|
|
6
41
|
"aide": {
|
|
7
42
|
"name": "AI-Driven Engineering (AIDE)",
|
|
8
43
|
"id": "aide",
|
|
@@ -77,7 +77,9 @@ from ._version import (
|
|
|
77
77
|
from ._agent_config import (
|
|
78
78
|
AGENT_CONFIG as AGENT_CONFIG,
|
|
79
79
|
DEFAULT_INIT_INTEGRATION as DEFAULT_INIT_INTEGRATION,
|
|
80
|
+
DEFAULT_INIT_INTEGRATION_ENV_VAR as DEFAULT_INIT_INTEGRATION_ENV_VAR,
|
|
80
81
|
SCRIPT_TYPE_CHOICES as SCRIPT_TYPE_CHOICES,
|
|
82
|
+
resolve_default_init_integration as resolve_default_init_integration,
|
|
81
83
|
)
|
|
82
84
|
from ._init_options import (
|
|
83
85
|
INIT_OPTIONS_FILE as INIT_OPTIONS_FILE,
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"""Agent configuration constants derived from the integration registry."""
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _build_agent_config() -> dict[str, dict[str, Any]]:
|
|
10
|
+
from .integrations import INTEGRATION_REGISTRY
|
|
11
|
+
config: dict[str, dict[str, Any]] = {}
|
|
12
|
+
for key, integration in INTEGRATION_REGISTRY.items():
|
|
13
|
+
if integration.config:
|
|
14
|
+
config[key] = dict(integration.config)
|
|
15
|
+
return config
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
AGENT_CONFIG: dict[str, dict[str, Any]] = _build_agent_config()
|
|
19
|
+
|
|
20
|
+
DEFAULT_INIT_INTEGRATION = "copilot"
|
|
21
|
+
|
|
22
|
+
#: Environment variable used to override the fallback integration that
|
|
23
|
+
#: ``specify init`` selects in non-interactive sessions. Follows the existing
|
|
24
|
+
#: ``SPECKIT_INTEGRATION_*`` namespace (see ``SPECKIT_INTEGRATION_<KEY>_EXECUTABLE``
|
|
25
|
+
#: and ``SPECKIT_INTEGRATION_CATALOG_URL``).
|
|
26
|
+
DEFAULT_INIT_INTEGRATION_ENV_VAR = "SPECKIT_INTEGRATION_DEFAULT"
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def resolve_default_init_integration() -> str:
|
|
30
|
+
"""Return the default init integration, honoring an env-var override.
|
|
31
|
+
|
|
32
|
+
Reads :data:`DEFAULT_INIT_INTEGRATION_ENV_VAR`
|
|
33
|
+
(``SPECKIT_INTEGRATION_DEFAULT``). When it names a registered integration
|
|
34
|
+
key, that key is returned; otherwise the hardcoded
|
|
35
|
+
:data:`DEFAULT_INIT_INTEGRATION` (``"copilot"``) is used. An invalid value
|
|
36
|
+
emits a warning to stderr rather than silently falling back, so operators
|
|
37
|
+
can tell a typo from an intentional default.
|
|
38
|
+
"""
|
|
39
|
+
override = (os.environ.get(DEFAULT_INIT_INTEGRATION_ENV_VAR) or "").strip()
|
|
40
|
+
if not override:
|
|
41
|
+
return DEFAULT_INIT_INTEGRATION
|
|
42
|
+
if override in AGENT_CONFIG:
|
|
43
|
+
return override
|
|
44
|
+
print(
|
|
45
|
+
f"Warning: {DEFAULT_INIT_INTEGRATION_ENV_VAR}='{override}' is not a "
|
|
46
|
+
f"recognized integration; falling back to '{DEFAULT_INIT_INTEGRATION}'. "
|
|
47
|
+
f"Choose from: {', '.join(sorted(AGENT_CONFIG.keys()))}.",
|
|
48
|
+
file=sys.stderr,
|
|
49
|
+
)
|
|
50
|
+
return DEFAULT_INIT_INTEGRATION
|
|
51
|
+
|
|
52
|
+
SCRIPT_TYPE_CHOICES: dict[str, str] = {
|
|
53
|
+
"sh": "POSIX Shell (bash/zsh)",
|
|
54
|
+
"ps": "PowerShell",
|
|
55
|
+
"py": "Python",
|
|
56
|
+
}
|
|
@@ -679,7 +679,7 @@ class CommandRegistrar:
|
|
|
679
679
|
_integ = get_integration(agent_name)
|
|
680
680
|
if _integ is not None:
|
|
681
681
|
_sep = _integ.invoke_separator_for_mode(registrar_writes_skills)
|
|
682
|
-
except
|
|
682
|
+
except (ImportError, ValueError, KeyError):
|
|
683
683
|
pass
|
|
684
684
|
_prefix = get_invocation_prefix(agent_name, registrar_writes_skills)
|
|
685
685
|
|
|
@@ -18,7 +18,7 @@ from urllib.request import url2pathname
|
|
|
18
18
|
from ..._assets import _locate_core_pack, _repo_root
|
|
19
19
|
from ..._download_security import MAX_JSON_CATALOG_BYTES, read_response_limited
|
|
20
20
|
from .. import BundlerError
|
|
21
|
-
from ..lib.yamlio import loads_json
|
|
21
|
+
from ..lib.yamlio import load_json, loads_json
|
|
22
22
|
from ..models.catalog import CatalogSource
|
|
23
23
|
from ..models.manifest import ComponentRef
|
|
24
24
|
|
|
@@ -145,13 +145,13 @@ def make_catalog_fetcher(*, allow_network: bool = True):
|
|
|
145
145
|
path = _file_url_to_path(parsed)
|
|
146
146
|
if not path.exists():
|
|
147
147
|
raise BundlerError(f"Catalog file not found: {path}")
|
|
148
|
-
return
|
|
148
|
+
return load_json(path)
|
|
149
149
|
|
|
150
150
|
if scheme == "" or _is_windows_drive_path(url):
|
|
151
151
|
path = Path(url)
|
|
152
152
|
if not path.exists():
|
|
153
153
|
raise BundlerError(f"Catalog file not found: {path}")
|
|
154
|
-
return
|
|
154
|
+
return load_json(path)
|
|
155
155
|
|
|
156
156
|
if scheme in ("http", "https"):
|
|
157
157
|
if not allow_network:
|
|
@@ -93,9 +93,11 @@ def build_bundle(
|
|
|
93
93
|
# extraction, but collapse to two canonical modes (0755 when any
|
|
94
94
|
# execute bit is set on the source, otherwise 0644) so identical
|
|
95
95
|
# inputs yield a byte-for-byte identical artifact.
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
with file_path.open("rb") as fh:
|
|
97
|
+
st = os.fstat(fh.fileno())
|
|
98
|
+
mode = 0o755 if st.st_mode & 0o111 else 0o644
|
|
99
|
+
info.external_attr = mode << 16
|
|
100
|
+
archive.writestr(info, fh.read())
|
|
99
101
|
|
|
100
102
|
return BuildResult(artifact_path=artifact_path, file_count=len(files))
|
|
101
103
|
|
|
@@ -119,6 +119,8 @@ def _run_init(integration: str, *, script_type: str, offline: bool = False) -> N
|
|
|
119
119
|
preset=None,
|
|
120
120
|
integration=integration,
|
|
121
121
|
integration_options=None,
|
|
122
|
+
extensions=None,
|
|
123
|
+
trust_extension_urls=False,
|
|
122
124
|
)
|
|
123
125
|
except typer.Exit as exc:
|
|
124
126
|
if exc.exit_code:
|
|
@@ -129,13 +131,13 @@ def _run_init(integration: str, *, script_type: str, offline: bool = False) -> N
|
|
|
129
131
|
|
|
130
132
|
def _resolve_init_integration(override: str | None, manifest) -> str:
|
|
131
133
|
"""Precedence (FR-013): explicit override → bundle-declared → default."""
|
|
132
|
-
from ..._agent_config import
|
|
134
|
+
from ..._agent_config import resolve_default_init_integration
|
|
133
135
|
|
|
134
136
|
if override:
|
|
135
137
|
return override
|
|
136
138
|
if manifest is not None and manifest.integration is not None:
|
|
137
139
|
return manifest.integration.id
|
|
138
|
-
return
|
|
140
|
+
return resolve_default_init_integration()
|
|
139
141
|
|
|
140
142
|
|
|
141
143
|
# ===== Consume =====
|
|
@@ -14,8 +14,8 @@ from rich.panel import Panel
|
|
|
14
14
|
|
|
15
15
|
from .._agent_config import (
|
|
16
16
|
AGENT_CONFIG,
|
|
17
|
-
DEFAULT_INIT_INTEGRATION,
|
|
18
17
|
SCRIPT_TYPE_CHOICES,
|
|
18
|
+
resolve_default_init_integration,
|
|
19
19
|
)
|
|
20
20
|
from .._assets import (
|
|
21
21
|
_locate_bundled_preset,
|
|
@@ -30,6 +30,145 @@ def _stdin_is_interactive() -> bool:
|
|
|
30
30
|
return sys.stdin.isatty()
|
|
31
31
|
|
|
32
32
|
|
|
33
|
+
def _ext_spec_is_url(ext_spec: str) -> bool:
|
|
34
|
+
"""Return True when *ext_spec* is an http(s) URL rather than a name/path."""
|
|
35
|
+
from urllib.parse import urlparse
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
return urlparse(ext_spec).scheme in ("http", "https")
|
|
39
|
+
except ValueError:
|
|
40
|
+
return False
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def _confirm_extension_url_trust(
|
|
44
|
+
url_specs: list[str], *, trust_override: bool
|
|
45
|
+
) -> dict[str, bool]:
|
|
46
|
+
"""Resolve trust for each URL-based extension before the Live display.
|
|
47
|
+
|
|
48
|
+
URL installs pull an arbitrary external extension, so they get the same
|
|
49
|
+
default-deny confirmation as ``extension add --from``. Returns a mapping of
|
|
50
|
+
``url_spec -> approved``. With *trust_override* every URL is pre-approved.
|
|
51
|
+
In a non-interactive session without the override, every URL is denied
|
|
52
|
+
(the prompt cannot be answered), mirroring the default-deny posture.
|
|
53
|
+
"""
|
|
54
|
+
from rich.markup import escape as _escape_markup
|
|
55
|
+
from rich.panel import Panel
|
|
56
|
+
|
|
57
|
+
approvals: dict[str, bool] = {}
|
|
58
|
+
interactive = _stdin_is_interactive()
|
|
59
|
+
for spec in url_specs:
|
|
60
|
+
if trust_override:
|
|
61
|
+
approvals[spec] = True
|
|
62
|
+
continue
|
|
63
|
+
if not interactive:
|
|
64
|
+
approvals[spec] = False
|
|
65
|
+
continue
|
|
66
|
+
console.print()
|
|
67
|
+
console.print(
|
|
68
|
+
Panel(
|
|
69
|
+
"[bold]You are installing an extension from an external URL that is not\n"
|
|
70
|
+
"listed in any of your configured extension catalogs.[/bold]\n\n"
|
|
71
|
+
f"URL: {_escape_markup(spec)}\n\n"
|
|
72
|
+
"Only install extensions from sources you trust.",
|
|
73
|
+
title="[bold yellow]⚠ Untrusted Source[/bold yellow]",
|
|
74
|
+
border_style="yellow",
|
|
75
|
+
padding=(1, 2),
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
console.print()
|
|
79
|
+
approvals[spec] = typer.confirm(
|
|
80
|
+
f"Install extension from {spec}?", default=False
|
|
81
|
+
)
|
|
82
|
+
return approvals
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _install_extension_during_init(project_path: Path, ext_spec: str, speckit_version: str) -> str:
|
|
86
|
+
"""Install a single extension during ``specify init``.
|
|
87
|
+
|
|
88
|
+
Handles bundled extension names, local directory paths, and HTTPS URLs.
|
|
89
|
+
Returns a short status message on success.
|
|
90
|
+
Raises ``ValueError`` on failure so the caller can convert it to a
|
|
91
|
+
tracker error without aborting the entire init.
|
|
92
|
+
"""
|
|
93
|
+
from urllib.parse import urlparse
|
|
94
|
+
|
|
95
|
+
from .._assets import _locate_bundled_extension
|
|
96
|
+
from ..extensions import ExtensionCatalog, ExtensionError, ExtensionManager
|
|
97
|
+
from ..extensions._commands import (
|
|
98
|
+
_resolve_catalog_extension,
|
|
99
|
+
install_extension_from_url,
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
manager = ExtensionManager(project_path)
|
|
103
|
+
|
|
104
|
+
# --- URL ---
|
|
105
|
+
parsed = urlparse(ext_spec)
|
|
106
|
+
if parsed.scheme in ("http", "https"):
|
|
107
|
+
try:
|
|
108
|
+
manifest = install_extension_from_url(
|
|
109
|
+
manager, project_path, ext_spec, speckit_version
|
|
110
|
+
)
|
|
111
|
+
except ExtensionError as exc:
|
|
112
|
+
raise ValueError(str(exc)) from exc
|
|
113
|
+
return f"{manifest.name} v{manifest.version} installed"
|
|
114
|
+
|
|
115
|
+
# --- Local path ---
|
|
116
|
+
if ext_spec.startswith(("./", "../", "/", "~/", ".\\", "..\\")) or Path(ext_spec).is_absolute():
|
|
117
|
+
source_path = Path(ext_spec).expanduser().resolve()
|
|
118
|
+
if not source_path.exists():
|
|
119
|
+
raise ValueError(f"Directory not found: {source_path}")
|
|
120
|
+
if not (source_path / "extension.yml").exists():
|
|
121
|
+
raise ValueError(f"No extension.yml found in {source_path}")
|
|
122
|
+
manifest = manager.install_from_directory(source_path, speckit_version)
|
|
123
|
+
return f"{manifest.name} v{manifest.version} installed"
|
|
124
|
+
|
|
125
|
+
# --- Bundled extension name or catalog ID ---
|
|
126
|
+
bundled_path = _locate_bundled_extension(ext_spec)
|
|
127
|
+
if bundled_path is not None:
|
|
128
|
+
if manager.registry.is_installed(ext_spec):
|
|
129
|
+
return "already installed"
|
|
130
|
+
manifest = manager.install_from_directory(bundled_path, speckit_version)
|
|
131
|
+
return f"{manifest.name} v{manifest.version} installed"
|
|
132
|
+
|
|
133
|
+
# Fall back to catalog
|
|
134
|
+
catalog = ExtensionCatalog(project_path)
|
|
135
|
+
ext_info, catalog_error = _resolve_catalog_extension(ext_spec, catalog, "add")
|
|
136
|
+
if catalog_error:
|
|
137
|
+
raise ValueError(f"Could not query extension catalog: {catalog_error}")
|
|
138
|
+
if not ext_info:
|
|
139
|
+
raise ValueError(f"Extension '{ext_spec}' not found in bundled extensions or catalog")
|
|
140
|
+
|
|
141
|
+
resolved_id = ext_info["id"]
|
|
142
|
+
if resolved_id != ext_spec:
|
|
143
|
+
bundled_path = _locate_bundled_extension(resolved_id)
|
|
144
|
+
if bundled_path is not None:
|
|
145
|
+
if manager.registry.is_installed(resolved_id):
|
|
146
|
+
return "already installed"
|
|
147
|
+
manifest = manager.install_from_directory(bundled_path, speckit_version)
|
|
148
|
+
return f"{manifest.name} v{manifest.version} installed"
|
|
149
|
+
|
|
150
|
+
if ext_info.get("bundled") and not ext_info.get("download_url"):
|
|
151
|
+
from ..extensions import REINSTALL_COMMAND
|
|
152
|
+
|
|
153
|
+
raise ValueError(
|
|
154
|
+
f"Extension '{resolved_id}' is bundled with spec-kit but not found in the installed package. "
|
|
155
|
+
f"Try reinstalling spec-kit: {REINSTALL_COMMAND}"
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
if not ext_info.get("_install_allowed", True):
|
|
159
|
+
catalog_name = ext_info.get("_catalog_name", "community")
|
|
160
|
+
raise ValueError(
|
|
161
|
+
f"Extension '{ext_spec}' is in the '{catalog_name}' catalog but installation is not allowed from that catalog"
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
zip_path = catalog.download_extension(resolved_id)
|
|
165
|
+
try:
|
|
166
|
+
manifest = manager.install_from_zip(zip_path, speckit_version)
|
|
167
|
+
finally:
|
|
168
|
+
zip_path.unlink(missing_ok=True)
|
|
169
|
+
return f"{manifest.name} v{manifest.version} installed"
|
|
170
|
+
|
|
171
|
+
|
|
33
172
|
def ensure_constitution_from_template(
|
|
34
173
|
project_path: Path, tracker: StepTracker | None = None
|
|
35
174
|
) -> None:
|
|
@@ -142,6 +281,16 @@ def register(app: typer.Typer) -> None:
|
|
|
142
281
|
"--integration-options",
|
|
143
282
|
help='Options for the integration (e.g. --integration-options="--commands-dir .myagent/cmds")',
|
|
144
283
|
),
|
|
284
|
+
extensions: list[str] | None = typer.Option(
|
|
285
|
+
None,
|
|
286
|
+
"--extension",
|
|
287
|
+
help="Install an extension during initialization (bundled name, local path, or HTTPS URL). Repeatable.",
|
|
288
|
+
),
|
|
289
|
+
trust_extension_urls: bool = typer.Option(
|
|
290
|
+
False,
|
|
291
|
+
"--trust-extension-urls",
|
|
292
|
+
help="Pre-authorize installing extensions from external URLs without the interactive trust prompt (required for non-interactive URL installs).",
|
|
293
|
+
),
|
|
145
294
|
):
|
|
146
295
|
"""
|
|
147
296
|
Initialize a new Specify project.
|
|
@@ -174,6 +323,10 @@ def register(app: typer.Typer) -> None:
|
|
|
174
323
|
specify init --here --integration gemini
|
|
175
324
|
specify init my-project --integration generic --integration-options="--commands-dir .myagent/commands/" # Bring your own agent; requires --commands-dir
|
|
176
325
|
specify init my-project --integration claude --preset healthcare-compliance # With preset
|
|
326
|
+
specify init my-project --integration copilot --extension git # With bundled extension
|
|
327
|
+
specify init my-project --extension git --extension selftest # Multiple extensions
|
|
328
|
+
specify init my-project --extension ./my-extensions/custom-ext # Local path extension
|
|
329
|
+
specify init my-project --extension https://example.com/extensions/my-ext.zip --trust-extension-urls # URL extension (non-interactive)
|
|
177
330
|
"""
|
|
178
331
|
# Lazy imports to avoid circular dependency — __init__.py imports this module
|
|
179
332
|
from .. import (
|
|
@@ -313,17 +466,18 @@ def register(app: typer.Typer) -> None:
|
|
|
313
466
|
raise typer.Exit(1)
|
|
314
467
|
selected_ai = integration
|
|
315
468
|
elif not _stdin_is_interactive():
|
|
469
|
+
default_integration = resolve_default_init_integration()
|
|
316
470
|
console.print(
|
|
317
|
-
f"[dim]Non-interactive session detected: defaulting to '{
|
|
471
|
+
f"[dim]Non-interactive session detected: defaulting to '{default_integration}'. "
|
|
318
472
|
"Use --integration to choose a different agent.[/dim]"
|
|
319
473
|
)
|
|
320
|
-
selected_ai =
|
|
474
|
+
selected_ai = default_integration
|
|
321
475
|
else:
|
|
322
476
|
ai_choices = {key: config["name"] for key, config in AGENT_CONFIG.items()}
|
|
323
477
|
selected_ai = select_with_arrows(
|
|
324
478
|
ai_choices,
|
|
325
479
|
"Choose your coding agent integration:",
|
|
326
|
-
|
|
480
|
+
resolve_default_init_integration(),
|
|
327
481
|
)
|
|
328
482
|
|
|
329
483
|
if not integration:
|
|
@@ -413,10 +567,31 @@ def register(app: typer.Typer) -> None:
|
|
|
413
567
|
("chmod", "Ensure scripts executable"),
|
|
414
568
|
("constitution", "Constitution setup"),
|
|
415
569
|
("workflow", "Install bundled workflow"),
|
|
416
|
-
("final", "Finalize"),
|
|
417
570
|
]:
|
|
418
571
|
tracker.add(key, label)
|
|
419
572
|
|
|
573
|
+
if extensions:
|
|
574
|
+
from rich.markup import escape as _escape_markup
|
|
575
|
+
|
|
576
|
+
for i, ext_spec in enumerate(extensions):
|
|
577
|
+
tracker.add(
|
|
578
|
+
f"extension-{i}", f"Install extension: {_escape_markup(ext_spec)}"
|
|
579
|
+
)
|
|
580
|
+
|
|
581
|
+
tracker.add("final", "Finalize")
|
|
582
|
+
|
|
583
|
+
# Resolve trust for URL-based extensions BEFORE entering the Live
|
|
584
|
+
# display: the confirmation prompt cannot be shown/answered underneath
|
|
585
|
+
# the Rich Live spinner. URL installs are default-deny unless the user
|
|
586
|
+
# confirms interactively or passes --trust-extension-urls.
|
|
587
|
+
extension_url_approvals: dict[str, bool] = {}
|
|
588
|
+
if extensions:
|
|
589
|
+
url_specs = [e for e in extensions if _ext_spec_is_url(e)]
|
|
590
|
+
if url_specs:
|
|
591
|
+
extension_url_approvals = _confirm_extension_url_trust(
|
|
592
|
+
url_specs, trust_override=trust_extension_urls
|
|
593
|
+
)
|
|
594
|
+
|
|
420
595
|
# Disable transient mode on Windows: PowerShell 5.1's legacy console
|
|
421
596
|
# hangs when Rich tries to restore cursor state via VT escape sequences.
|
|
422
597
|
_transient = sys.platform != "win32"
|
|
@@ -626,6 +801,46 @@ def register(app: typer.Typer) -> None:
|
|
|
626
801
|
continuing="Continuing without the optional preset.",
|
|
627
802
|
)
|
|
628
803
|
|
|
804
|
+
# Install extensions specified via --extension
|
|
805
|
+
if extensions:
|
|
806
|
+
from rich.markup import escape as _escape_markup
|
|
807
|
+
|
|
808
|
+
from ..extensions._commands import _refresh_events_and_warn
|
|
809
|
+
|
|
810
|
+
speckit_ver = get_speckit_version()
|
|
811
|
+
any_extension_installed = False
|
|
812
|
+
for i, ext_spec in enumerate(extensions):
|
|
813
|
+
tracker.start(f"extension-{i}")
|
|
814
|
+
# Skip URL extensions the user did not confirm as trusted
|
|
815
|
+
# (default-deny; resolved before the Live display).
|
|
816
|
+
if _ext_spec_is_url(ext_spec) and not extension_url_approvals.get(
|
|
817
|
+
ext_spec, False
|
|
818
|
+
):
|
|
819
|
+
tracker.error(
|
|
820
|
+
f"extension-{i}",
|
|
821
|
+
"skipped: untrusted URL not confirmed "
|
|
822
|
+
"(use --trust-extension-urls)",
|
|
823
|
+
)
|
|
824
|
+
continue
|
|
825
|
+
try:
|
|
826
|
+
status_msg = _install_extension_during_init(
|
|
827
|
+
project_path, ext_spec, speckit_ver
|
|
828
|
+
)
|
|
829
|
+
tracker.complete(f"extension-{i}", status_msg)
|
|
830
|
+
any_extension_installed = True
|
|
831
|
+
except Exception as ext_err:
|
|
832
|
+
sanitized_ext = str(ext_err).replace("\n", " ").strip()
|
|
833
|
+
tracker.error(
|
|
834
|
+
f"extension-{i}",
|
|
835
|
+
f"failed: {_escape_markup(sanitized_ext[:120])}",
|
|
836
|
+
)
|
|
837
|
+
|
|
838
|
+
# Refresh native event configuration once after the batch so
|
|
839
|
+
# that an extension declaring ``events:`` has its hooks
|
|
840
|
+
# activated, mirroring the ``extension add`` path.
|
|
841
|
+
if any_extension_installed:
|
|
842
|
+
_refresh_events_and_warn(project_path)
|
|
843
|
+
|
|
629
844
|
# Seed the constitution AFTER preset installation so that a
|
|
630
845
|
# preset-provided constitution-template (resolved via the
|
|
631
846
|
# priority stack) wins over the core template.
|
|
@@ -895,7 +895,7 @@ def collect_extension_events(project_root: Path) -> ResolvedEvents:
|
|
|
895
895
|
continue
|
|
896
896
|
try:
|
|
897
897
|
data = yaml.safe_load(ext_yml.read_text(encoding="utf-8")) or {}
|
|
898
|
-
except yaml.YAMLError:
|
|
898
|
+
except (UnicodeDecodeError, yaml.YAMLError):
|
|
899
899
|
continue
|
|
900
900
|
if not isinstance(data, dict):
|
|
901
901
|
continue
|