From 207c5cef735965c34498d05b263b4edc90ecc090 Mon Sep 17 00:00:00 2001 From: Manfred Riem <15701806+mnriem@users.noreply.github.com> Date: Fri, 1 May 2026 12:54:34 -0500 Subject: [PATCH] feat: emit init-time notice for git extension default change (#2165) Add a non-blocking Panel notice during `specify init` when the git extension auto-enables, informing users that starting in v0.10.0 this will require explicit opt-in via `specify extension add git`. - src/specify_cli/__init__.py: track successful git extension install and display yellow "Notice: Git Default Changing" panel - tests/integrations/test_cli.py: integration test validating notice content (v0.10.0 timeline, opt-in messaging, migration command) - docs/reference/core.md: user-facing NOTE about the upcoming change Closes #2165 --- docs/reference/core.md | 4 ++++ src/specify_cli/__init__.py | 15 +++++++++++++++ tests/integrations/test_cli.py | 26 ++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/docs/reference/core.md b/docs/reference/core.md index fdab05a02b..aeef06ab79 100644 --- a/docs/reference/core.md +++ b/docs/reference/core.md @@ -22,6 +22,10 @@ specify init [] Creates a new Spec Kit project with the necessary directory structure, templates, scripts, and AI coding agent integration files. +> [!NOTE] +> The git extension is currently enabled by default during `specify init`. +> Starting in `v0.10.0`, it will require explicit opt-in. To add it after init, run `specify extension add git`. + Use `` 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. ### Examples diff --git a/src/specify_cli/__init__.py b/src/specify_cli/__init__.py index d5f5aba2d5..01153976ea 100644 --- a/src/specify_cli/__init__.py +++ b/src/specify_cli/__init__.py @@ -1266,6 +1266,8 @@ def init( ]: tracker.add(key, label) + git_default_notice = False + with Live(tracker.render(), console=console, refresh_per_second=8, transient=True) as live: tracker.attach_refresh(lambda: live.update(tracker.render())) try: @@ -1349,6 +1351,7 @@ def init( manager.install_from_directory( bundled_path, get_speckit_version() ) + git_default_notice = True git_messages.append("extension installed") else: git_has_error = True @@ -1519,6 +1522,18 @@ def init( console.print() console.print(deprecation_notice) + if git_default_notice: + default_change_notice = Panel( + "The git extension is currently enabled by default during [bold]specify init[/bold].\n" + "Starting in [bold]v0.10.0[/bold], this will require explicit opt-in.\n" + "Use [bold]specify extension add git[/bold] after init when needed.", + title="[yellow]Notice: Git Default Changing[/yellow]", + border_style="yellow", + padding=(1, 2), + ) + console.print() + console.print(default_change_notice) + steps_lines = [] if not here: steps_lines.append(f"1. Go to the project folder: [cyan]cd {project_name}[/cyan]") diff --git a/tests/integrations/test_cli.py b/tests/integrations/test_cli.py index df48323ed2..7cbfe7f0d4 100644 --- a/tests/integrations/test_cli.py +++ b/tests/integrations/test_cli.py @@ -473,6 +473,32 @@ def test_no_git_emits_deprecation_warning(self, tmp_path): assert "will be removed" in normalized_output assert "git extension will no longer be enabled by default" in normalized_output + def test_default_git_auto_enable_emits_notice(self, tmp_path): + """Default git auto-enable emits notice about the v0.10.0 opt-in change.""" + from typer.testing import CliRunner + from specify_cli import app + + project = tmp_path / "git-default-notice" + project.mkdir() + old_cwd = os.getcwd() + try: + os.chdir(project) + runner = CliRunner() + result = runner.invoke(app, [ + "init", "--here", "--ai", "claude", "--script", "sh", + "--ignore-agent-tools", + ], catch_exceptions=False) + finally: + os.chdir(old_cwd) + + normalized_output = _normalize_cli_output(result.output) + assert result.exit_code == 0, result.output + # Check for key message components (notice may have box-drawing chars) + assert "git extension is currently enabled by default" in normalized_output + assert "v0.10.0" in normalized_output + assert "explicit opt-in" in normalized_output + assert "specify extension add git" in normalized_output + def test_git_extension_commands_registered(self, tmp_path): """Git extension commands are registered with the agent during init.""" from typer.testing import CliRunner