You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(integration): add none for shared scaffolding only - #5030
Add none as an ordinary registered built-in integration. It returns an empty command-template list, so inherited setup creates no files. Its teardown is manifest-only: it never invokes shared event cleanup for files it did not create. Teams can initialize shared Spec Kit scaffolding without generating agent commands, skills, settings, or native events:
specify init my-project --integration none
The existing lifecycle handles init, install, use, switch, upgrade, and uninstall without changes. none has normal installed/default metadata and an empty owned-file manifest; shared .specify/ infrastructure remains. SPECKIT_INTEGRATION_DEFAULT=none selects it through the existing default configuration.
Use specify integration switch <key> to replace it. none declares multi_install_safe = True, so another declared-safe integration can coexist without --force, with healthy status:
specify integration install kiro-cli
specify integration use kiro-cli
Partners not declared safe, including Copilot, still require the existing --force override and still produce unsafe-multi-install status while coinstalled. No name-based collision exception or automatic fallback installation is added.
The cumulative diff is 10 files, +178/-14. Executable changes remain the adapter and two-line registry wiring. Supporting changes are catalog metadata, focused tests, reference documentation, and a docstring/design clarification that an integration emitting no files may be multi-install safe. The generic contract test verifies rootless setup creates and owns no files; existing static-root, overlap, and disjoint-manifest checks remain. Shared-runtime executable code is unchanged. All earlier contribution-observer, preset, extension, status, CLI, and init-only sentinel changes remain removed.
Remaining review concerns: generic CLI output still recommends unavailable commands and labels none IDE-based. Separately, switching to Copilot still deletes an unowned dispatcher in Copilot's incoming event setup; the none teardown fix does not change that independent shared-event behavior. These are not claimed fixed here.
Testing
Tested locally with uv run specify --help
Ran existing tests with uv sync && uv run pytest
Tested with a sample project (if applicable)
Used the worktree's own virtual environment, as recommended in CONTRIBUTING.md, rather than the literal uv run commands in the unchecked template items.
.venv/bin/python -m pytest -p tests.specify_cli.presets._fixtures tests -q --tb=short — the earlier full run, before the final adapter/test simplification, completed without deselections: 12,746 passed, 101 skipped, 1 failed in 1,078.37 seconds. The sole failure was a rendering-only registry expectation for none; that expectation was corrected. The earlier Claude upgrade failure no longer occurred once the superseded framework changes were removed. The complete suite has not been repeated after the final simplification.
.venv/bin/python -m pytest tests/integrations/test_integration_none.py -q --tb=short — before the safety/teardown fixes: 4 failed, 2 passed, reproducing the false safety declaration, rejected unforced coexistence, and unowned dispatcher deletion with and without --force.
.venv/bin/python -m pytest -p tests.specify_cli.presets._fixtures tests/integrations/test_integration_none.py tests/integrations/test_registry.py tests/test_agent_config_consistency.py tests/extensions/github/test_github_extension.py -q --tb=short — 1,219 passed, 1 skipped after the fixes, covering every changed test module.
Focused adapter tests cover no generated files or ownership; explicit and environment-configured init selection; normal metadata; install, use, switch, upgrade, and uninstall; default reselection; rejected unsupported options; preservation of shared scaffolding and user files; dispatcher preservation under forced/unforced teardown; unforced coexistence and healthy status with a declared-safe agent; and continued rejection of an unsafe partner. They reuse the existing lifecycle rather than duplicating framework-level coverage.
Actual-CLI smoke checks passed 20 subprocess invocations against disposable projects: the existing 13-command lifecycle scenario plus seven calls verifying unowned dispatcher preservation on none uninstall, unforced Kiro CLI coexistence, healthy status, and unsafe-partner rejection. A separate two-call reproduction confirmed that incoming Copilot setup still deletes an unowned dispatcher; that independent limitation remains open. Temporary projects were removed afterward.
AI Disclosure
I did not use AI assistance for this contribution
I did use AI assistance (fill in the disclosure below)
AI disclosure: GitHub Copilot, powered by GPT-6.1 Sol (model ID: gpt-6.1-sol), acted autonomously on behalf of mnriem within the contributor-requested scope. Reasoning effort was not exposed. Assistance included investigation, adapter implementation, tests, actual-CLI validation, documentation, removal of superseded changes, branch cleanup, commit authorship, and this PR description. This does not claim human line-by-line review.
Addressed all three findings from review 5577740091 in commit ef8faab.
Integration status now accepts initialized projects with no active agent, including cleared active keys after the last uninstall, while still checking the shared manifest. Integrated projects with missing selection metadata continue to fail; missing or modified shared files are reported.
Optional preset and extension installation checks active-agent state before entering command/skill registration. Event refresh skips adapter loading when there are no installed integrations. Regression coverage includes a loader sentinel and a corrupt leftover package registry.
Installing the first integration registers enabled extension and preset contributions after saving active metadata, then resynchronizes managed-file hashes. Secondary installs still defer contribution registration until selected.
Regression evidence: the initial review-focused selection produced 6 failures and 1 pass before the fixes, then 7 passes afterward. Additional last-uninstall status variants are included in the final targeted run.
Validation:
.venv/bin/python -m pytest tests/specify_cli/test_command_init.py tests/specify_cli/integrations/test_command_install.py tests/specify_cli/integrations/test_command_uninstall.py tests/specify_cli/integrations/test_command_status.py tests/specify_cli/integrations/test_installed_adapters.py tests/specify_cli/integrations/test_lifecycle.py tests/specify_cli/presets/test_manager.py tests/specify_cli/presets/test_manager_commands.py tests/specify_cli/presets/test_manager_skills.py tests/specify_cli/events/test_events.py tests/test_extensions.py tests/test_presets.py tests/integrations/test_cli.py -q --tb=short
Result: 1,749 passed, 3 warnings.
.venv/bin/python -m pytest tests/specify_cli/test_command_init.py tests/specify_cli/integrations/test_command_status.py tests/specify_cli/test_file_policy.py tests/test_agent_config_consistency.py -q --tb=short
Result: 294 passed on the final changes, including the additional last-uninstall status cases.
git diff --check
Result: passed.
Also ran the actual .venv/bin/specify executable in separate subprocesses against a disposable dummy project: init without an integration plus the Git extension and a team preset, status, install Copilot, status, uninstall Copilot, status, re-init without an integration, and status. All commands succeeded. Assertions verified real extension/preset artifacts, the preset's plan override, synchronized managed-file hashes, and preservation of shared scaffolding. The dummy project was removed.
AI disclosure: posted on behalf of mnriem by GitHub Copilot using GPT-6.1 Sol (gpt-6.1-sol), autonomous execution within the user-approved scope; reasoning effort was not exposed in session metadata. AI assistance covered investigation, implementation, tests, documentation, commit authorship, and this review response. No human line-by-line review is claimed.
Integration-free shared-manifest recovery now consistently recommends specify init --here --force --integration none, with a warning to review customized files first. First-install extension registration no longer forces replacement of existing skills, including customized outputs retained by an earlier uninstall.
Newly generated contribution files are recorded with hashes using observed registration writes, without adopting pre-existing files or shared metadata. Uninstall removes unchanged extension and preset outputs while preserving edits. Upgrade captures regenerated contributions too, and extension layout reconciliation now clears stale skill tracking when manifest cleanup has already removed those outputs.
Also strengthened the earlier adapter-loading fix: direct inactive registration helpers skip adapter-loading contexts and return before constructing registrars. Existing integration-free status and optional-component regressions remain covered.
Automated validation:
.venv/bin/python -m pytest tests/specify_cli/test_command_init.py tests/specify_cli/integrations/test_command_status.py tests/specify_cli/integrations/test_helpers.py -q -k 'first_integration or inactive_registration_helpers or status_checks_shared_manifest_without_integration or registration_ownership' --tb=short
Result: 21 passed. The initial review-regression selection reproduced 11 failures before the fixes.
.venv/bin/python -m pytest tests/specify_cli/test_command_init.py tests/specify_cli/integrations/test_helpers.py tests/specify_cli/integrations/test_registration.py tests/specify_cli/integrations/test_command_install.py tests/specify_cli/integrations/test_command_uninstall.py tests/specify_cli/integrations/test_command_upgrade.py tests/specify_cli/integrations/test_command_status.py tests/specify_cli/integrations/test_lifecycle.py tests/specify_cli/presets/test_manager.py tests/specify_cli/presets/test_manager_commands.py tests/specify_cli/presets/test_manager_skills.py tests/specify_cli/events/test_events.py tests/test_extensions.py tests/test_presets.py tests/test_extension_registration.py tests/specify_cli/test_file_policy.py tests/test_agent_config_consistency.py -q --tb=short
Result: 1,313 passed, 15 warnings (legacy layouts and deliberately simulated composition/registration failures).
.venv/bin/python -m pytest tests/specify_cli/integrations/test_installed_adapters.py -q -k 'registration or skill_directory_uses_pinned or contributions_follow_active' --tb=short
Result: 33 passed.
git diff --check
Result: passed.
Separately exercised the standalone .venv/bin/specify executable in a disposable project: init without an integration plus Git extension and local team preset, first Copilot install, verification of every recorded SHA-256 hash, uninstall, reinstall, and uninstall again. Unchanged extension and preset-only outputs were removed, pre-existing and customized skills survived, shared scaffolding remained, and integration-free status reported ok. This was automated subprocess validation, not a claim of human testing.
AI disclosure: posted on behalf of @mnriem by GitHub Copilot, powered by GPT-6.1 Sol (gpt-6.1-sol), acting autonomously. Code changes, regression tests, validation, commit, and this review summary were AI-authored/executed; no line-by-line human review is claimed. The reasoning-effort setting is not exposed.
First-install preservation does not cover native-skills integrations. After init --integration none --extension git, create a team-owned .agents/skills/speckit-git-feature/SKILL.md, then run integration install codex: this helper reaches register_commands_for_agent, whose writer overwrites the existing file. The force=False guard protects only the separate companion-skills pass. This can also overwrite edits preserved by an earlier uninstall, contrary to design/integration.md, “Ownership and lifecycle.” Pass a preserve-existing policy through native-skills registration for first installs and extend the Copilot preservation test to Codex.
AI disclosure: GitHub Copilot performed automated review for the requester; model/settings unavailable.
Integration manifests now identify component-produced files separately from core setup outputs. Forced re-init and upgrade retain those files and their original ownership hashes before stale-core cleanup, including when an integration is inactive or its extension is disabled or unreadable. Existing layout reconciliation still retires old component outputs only after replacement succeeds.
Component installation, removal, update, and reconciliation synchronize owning manifests from observed writes and removals, including whole skill-directory removal. Re-registration updates only affected hashes rather than re-baselining every tracked file. Pre-existing files are not adopted, unrelated edits keep their baselines, and update rollback preserves restored user edits. New historical outputs are attributed to the integration whose existing output root they belong to.
Regression coverage includes forced re-init followed by uninstall; extension and preset removal followed by status; real extension/preset update commands followed by upgrade without --force; extension update rollback; disabled, corrupt, and inactive upgrade preservation; and the existing Bob layout-failure case extended to integration-owned contributions. The initial focused run reproduced the lifecycle failures before implementation.
Validation:
.venv/bin/python -m pytest tests/specify_cli/test_command_init.py tests/specify_cli/integrations/test_contributions.py tests/specify_cli/integrations/test_command_upgrade.py -q -k 'forced_reinit_retains or component_removal_synchronizes or component_regeneration_rehashes or component_update_then_upgrade or upgrade_retains_owned or layout_change_preserves_extension_artifacts_when_reregistration_fails or contribution_provenance or retention or synchronization or new_core_output or failed_component or new_historical' --tb=short
Result: 24 passed, 2 expected legacy-layout warnings.
.venv/bin/python -m pytest -p tests.specify_cli.presets._fixtures tests/specify_cli/test_command_init.py tests/specify_cli/integrations/test_contributions.py tests/specify_cli/integrations/test_helpers.py tests/integrations/test_manifest.py tests/specify_cli/integrations/test_command_install.py tests/specify_cli/integrations/test_command_uninstall.py tests/specify_cli/integrations/test_command_upgrade.py tests/specify_cli/integrations/test_command_status.py tests/specify_cli/integrations/test_lifecycle.py tests/specify_cli/presets/test_manager.py tests/specify_cli/presets/test_manager_commands.py tests/specify_cli/presets/test_manager_skills.py tests/specify_cli/events/test_events.py tests/test_extensions.py tests/test_presets.py tests/test_extension_registration.py tests/specify_cli/test_file_policy.py tests/test_agent_config_consistency.py tests/specify_cli/extensions/test_command_update.py tests/specify_cli/extensions/test_command_update_transaction.py tests/specify_cli/presets/test_command_update.py tests/integration/test_preset_update_workflow.py -q --tb=short
Result: 1,479 passed, 47 warnings from legacy layouts and simulated composition/registration failures. The existing preset fixture module is loaded explicitly for the preset update command tests.
.venv/bin/python -m pytest tests/specify_cli/integrations/test_installed_adapters.py -q -k 'registration or skill_directory_uses_pinned or contributions_follow_active or failed_switch_restores_preset_composition_cache or overlapping_own_output_roots or extension_event_refresh_loads' --tb=short
Result: 52 passed.
git diff --check
Result: passed.
Also ran five standalone .venv/bin/specify subprocess scenarios in disposable projects: forced re-init/uninstall, preset update followed by no-force upgrade and component removals, disabled-extension upgrade, corrupt-extension upgrade, and inactive-integration upgrade. All ownership/content assertions passed, with zero missing or modified managed files. The deliberately forced Copilot/Claude multi-install retained its expected unsafe-multi-install diagnostic; the other four scenarios reported status ok. This was automated validation, not a claim of human testing.
AI disclosure: posted on behalf of @mnriem by GitHub Copilot, powered by GPT-6.1 Sol (gpt-6.1-sol), acting autonomously. Code, tests, validation, commit, and this summary were AI-authored/executed; no line-by-line human review is claimed. The reasoning-effort setting is not exposed.
Save active agent options before registering contributions
src/specify_cli/command_init.py:801
Persist the new active-agent options before re-registering contributions. After integration-free init with an extension and preset, init --here --integration copilot --force reaches this block while init-options.json still has null agent keys. Preset registration therefore skips preset-only commands, and extension registration emits command-mode files instead of Copilot's default skills. The new ai/ai_skills values are not saved until line 924, so init succeeds with incomplete or incorrectly formatted contributions. Move this block after active metadata is saved and add coverage for forced re-init directly from the none state.
AI review for the requester: GitHub Copilot; model/settings unavailable; autonomous analysis.
Preserve existing native integration skills during registration
First-install registration still overwrites existing extension skills for native-skill integrations such as Claude and Codex. After init --integration none --extension git, create .claude/skills/speckit-git-feature/SKILL.md, then install Claude: registration reaches agents.CommandRegistrar.register_commands(), whose writer replaces the file unconditionally. The default force=False protects only the separate extension-skills pass used by Copilot, not this path. This also destroys edited skills preserved by a previous uninstall, contrary to design/integration.md, “Ownership and lifecycle.” Propagate a preserve-existing policy through native-skill registration and cover this round trip beyond Copilot.
AI review for the requester: GitHub Copilot; model/settings unavailable; autonomous analysis.
Reworked in e65b350 at mnriem's direction: none is a registered no-op integration using the existing lifecycle, not an init-only sentinel. Removed the old init bypasses; no new artifact-free capability, registration guard, collision exception, or generic lifecycle fix is included. Ordinary multi-install safety remains unchanged, including --force for coexistence. Supporting edits update obsolete sentinel assumptions and documentation.
The full suite completed without deselections: 12,263 passed, 71 skipped, 2 failed. The new registry-expectation failure was corrected, then every changed test module passed: 378 passed, 1 skipped. The other failure, Claude's test_upgrade_reapplies_option_to_preset_overrides, was independently reproduced unchanged at the pre-pivot committed HEAD b986a1c and remains outside this scope. The complete suite was not repeated after the test-only correction. Actual CLI validation also passed 13 subprocess invocations against disposable projects. The PR description contains exact automated commands and results.
AI disclosure: Posted on behalf of mnriem by GitHub Copilot, powered by GPT-6.1 Sol (gpt-6.1-sol), operating autonomously within the contributor-approved scope; reasoning effort was not exposed. AI assistance included investigation, code, tests, documentation, commit authorship, and this response. This does not claim human line-by-line review.
Reinitialization drops ownership records without loading prior manifest
src/specify_cli/command_init.py:722
init --here permits re-initialization without --force after confirmation. This guard then skips loading the previous manifest, but setup still saves a replacement at line 762. For a project with owned extension/preset contributions, their files remain on disk while their ownership records disappear, so later integration uninstall leaves them behind. Load the previous manifest whenever the target directory already existed, independently of overwrite consent or re-registration timing. Add a regression for the confirmation path.
Component removal leaves ownership for missing outputs
src/specify_cli/extensions/__init__.py:3539
Removing a component does not clear ownership of its already-missing outputs. For example, delete an owned Git extension skill, then remove the extension. _find_extension_skill_dirs() skips the missing SKILL.md, so the observer receives no removal and leaves its manifest entry intact. retain_contributions() then carries that entry through every upgrade/re-init, and status keeps reporting a missing managed file although its component is no longer installed. Explicit component removal should retire its absent output records as well as files actually deleted. Add a removal regression with an already-missing contribution.
The contribution observer, manifest provenance, and install/upgrade/manager changes introduce shared lifecycle behavior for existing integrations, not just wiring for none. Registration gating and integration-free status handling also change shared behavior. design/integration.md, “Integration delivery boundary” (441–451), and CONTRIBUTING.md:68–79 require these changes in a separately justified prerequisite PR, with coverage independent of the new integration. Please extract the shared changes and their tests, then reference that prerequisite here. The description's claim that no registration/install/status changes are needed should also match the delivered scope.
Switching to a not-yet-installed integration produces false recovery warnings. command_switch.py:152–197 tears down the outgoing integration, deleting its manifest, before invoking the newly decorated extension/preset cleanup methods. The selection file still lists the outgoing key, so both observers warn that contribution cleanup may need manual recovery although the switch succeeds. Skip an absent manifest here; status already diagnoses missing manifests. Keep warnings for unreadable or invalid manifests, and assert successful switch output contains no synchronization warning.
Recursive removal records descendant names but not their original hashes. Extension updates delete whole skill directories, then regeneration first observes each SKILL.md as absent. If installation fails and rollback restores a customized skill, finalization adopts the restored user bytes as the managed baseline. A standard-library reproduction confirmed that a later non-forced uninstall deletes that customization. Snapshot tracked descendants before directory removal so restored bytes retain their original baseline. Add a failed-update regression using an edited contribution, not only an unrelated core file.
extension update refreshes native events before this observer exits (extensions/_command_update_transaction.py:912). Event refresh independently loads and saves the integration manifest, but owner is still the pre-update snapshot. When command output also changes, this save drops newly recorded dispatcher/settings ownership or restores retired event records. A standard-library check confirmed both new event records disappear while their files remain, breaking event cleanup and dispatcher reference counting. Finish contribution synchronization before event refresh, or merge the observed changes into the latest manifest without overwriting event ownership or modes. Cover event additions and removals during updates.
Retaining contributions exposes an unobserved deletion in Qoder's legacy migration. _retire_legacy_flat_extension_commands() deletes replaced commands with plain Path.unlink() (extensions/__init__.py:3931), so synchronization never removes their retained manifest entries. The updated migration test now marks those legacy paths as contributions but checks only the filesystem. After upgrade, status reports the deliberately deleted commands as missing, and later upgrades retain them again. Use the observed unlink helper for these deletions and assert the migrated manifest/status is clean.
Rebuilt the branch as one integration-only commit, 8ff7b7c, at mnriem's direction. The cumulative PR diff is now eight files. Production changes are limited to the 26-line no-op adapter and its two-line registry wiring; the remaining files are its catalog entry, reference documentation, adapter tests, and three existing registry-consistency expectations. All earlier shared-runtime, CLI, contribution-ownership, preset, extension, and lifecycle changes are removed rather than retained beneath the new adapter.
The complete suite ran without deselections: 12,746 passed, 101 skipped, and one rendering-only registry expectation failed. Corrected that test-only expectation, then reran every changed test module: 1,163 passed, 1 skipped. The complete suite was not repeated after that correction; runtime code was unchanged. The earlier Claude failure no longer occurs. Actual CLI smoke validation passed 13 subprocess invocations against disposable projects. Exact automated commands and results are in the updated PR description.
AI disclosure: Posted on behalf of mnriem by GitHub Copilot using GPT-6.1 Sol (gpt-6.1-sol), acting autonomously within the contributor-approved scope; reasoning effort was not exposed. Assistance included code investigation, implementation, tests, documentation, history cleanup, commit authorship, and this response. This does not claim human line-by-line review.
Reuse the base setup implementation with an empty template list. Keep focused positive and negative integration coverage without duplicating shared lifecycle tests, and shorten the reference documentation.
Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
The 15 earlier superseded threads remain resolved. Resolved the two coexistence-documentation threads: none now declares multi-install safety, ordinary coexistence with a declared-safe partner works without --force, status is healthy, and the documentation no longer recommends blanket forced coexistence. Unsafe partners remain restricted by the unchanged collision policy.
Implemented manifest-only none teardown. Forced/unforced regressions and public CLI uninstall preserve an unowned .specify/events.py. The ownership thread remains open because a separate reproduced incoming Copilot setup path still deletes that file; no shared-event runtime changes are included.
The CLI guidance/classification thread also remains open: generic init still recommends unavailable commands, and list/check still labels none IDE-based.
Validation: 1,219 passed, 1 skipped across all changed test modules; 20 successful actual-CLI lifecycle/safety subprocess calls; focused Ruff and git diff --check passed. New regressions failed before the fix. The full suite was not repeated after the latest changes. The PR description records the historical full-suite result separately.
Two threads remain open. No new review request while those concerns remain unresolved.
AI disclosure: GitHub Copilot, GPT-6.1 Sol (gpt-6.1-sol), autonomous on behalf of mnriem; reasoning effort not exposed. AI generated this review summary.
Declare none multi-install safe and limit teardown to its own manifest. Verify empty-output integrations through the general safety contract while retaining static-root and collision checks. Cover healthy unforced coexistence, unsafe-partner rejection, and preservation of unowned event dispatchers.
Assisted-by: GitHub Copilot (model: GPT-6.1 Sol, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
triage-nice-to-haveVerdict: evidence-backed fix or greenlit feature — land after review
2 participants
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Add
noneas an ordinary registered built-in integration. It returns an empty command-template list, so inherited setup creates no files. Its teardown is manifest-only: it never invokes shared event cleanup for files it did not create. Teams can initialize shared Spec Kit scaffolding without generating agent commands, skills, settings, or native events:The existing lifecycle handles init, install, use, switch, upgrade, and uninstall without changes.
nonehas normal installed/default metadata and an empty owned-file manifest; shared.specify/infrastructure remains.SPECKIT_INTEGRATION_DEFAULT=noneselects it through the existing default configuration.Use
specify integration switch <key>to replace it.nonedeclaresmulti_install_safe = True, so another declared-safe integration can coexist without--force, with healthy status:Partners not declared safe, including Copilot, still require the existing
--forceoverride and still produceunsafe-multi-installstatus while coinstalled. No name-based collision exception or automatic fallback installation is added.The cumulative diff is 10 files, +178/-14. Executable changes remain the adapter and two-line registry wiring. Supporting changes are catalog metadata, focused tests, reference documentation, and a docstring/design clarification that an integration emitting no files may be multi-install safe. The generic contract test verifies rootless setup creates and owns no files; existing static-root, overlap, and disjoint-manifest checks remain. Shared-runtime executable code is unchanged. All earlier contribution-observer, preset, extension, status, CLI, and init-only sentinel changes remain removed.
Remaining review concerns: generic CLI output still recommends unavailable commands and labels
noneIDE-based. Separately, switching to Copilot still deletes an unowned dispatcher in Copilot's incoming event setup; thenoneteardown fix does not change that independent shared-event behavior. These are not claimed fixed here.Testing
uv run specify --helpuv sync && uv run pytestUsed the worktree's own virtual environment, as recommended in CONTRIBUTING.md, rather than the literal
uv runcommands in the unchecked template items..venv/bin/python -m pytest -p tests.specify_cli.presets._fixtures tests -q --tb=short— the earlier full run, before the final adapter/test simplification, completed without deselections: 12,746 passed, 101 skipped, 1 failed in 1,078.37 seconds. The sole failure was a rendering-only registry expectation fornone; that expectation was corrected. The earlier Claude upgrade failure no longer occurred once the superseded framework changes were removed. The complete suite has not been repeated after the final simplification..venv/bin/python -m pytest tests/integrations/test_integration_none.py -q --tb=short— before the safety/teardown fixes: 4 failed, 2 passed, reproducing the false safety declaration, rejected unforced coexistence, and unowned dispatcher deletion with and without--force..venv/bin/python -m pytest -p tests.specify_cli.presets._fixtures tests/integrations/test_integration_none.py tests/integrations/test_registry.py tests/test_agent_config_consistency.py tests/extensions/github/test_github_extension.py -q --tb=short— 1,219 passed, 1 skipped after the fixes, covering every changed test module..venv/bin/python -m ruff check --select E4,E7,E9,F,S602,S604,S605 src/specify_cli/integrations/none/__init__.py tests/integrations/test_integration_none.py tests/integrations/test_registry.py— passed..venv/bin/specify --help— passed.git diff --check— passed.Focused adapter tests cover no generated files or ownership; explicit and environment-configured init selection; normal metadata; install, use, switch, upgrade, and uninstall; default reselection; rejected unsupported options; preservation of shared scaffolding and user files; dispatcher preservation under forced/unforced teardown; unforced coexistence and healthy status with a declared-safe agent; and continued rejection of an unsafe partner. They reuse the existing lifecycle rather than duplicating framework-level coverage.
Actual-CLI smoke checks passed 20 subprocess invocations against disposable projects: the existing 13-command lifecycle scenario plus seven calls verifying unowned dispatcher preservation on none uninstall, unforced Kiro CLI coexistence, healthy status, and unsafe-partner rejection. A separate two-call reproduction confirmed that incoming Copilot setup still deletes an unowned dispatcher; that independent limitation remains open. Temporary projects were removed afterward.
AI Disclosure
AI disclosure: GitHub Copilot, powered by GPT-6.1 Sol (model ID:
gpt-6.1-sol), acted autonomously on behalf of mnriem within the contributor-requested scope. Reasoning effort was not exposed. Assistance included investigation, adapter implementation, tests, actual-CLI validation, documentation, removal of superseded changes, branch cleanup, commit authorship, and this PR description. This does not claim human line-by-line review.