From 22fe7265a2175d8f54972ed108395954424ab7cd Mon Sep 17 00:00:00 2001 From: Manu Date: Sun, 17 May 2026 20:32:24 -0600 Subject: [PATCH 1/2] fix(BUG-001): correct Copilot verification + gate config on extension presence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two issues fixed together (same code block, both surfaced 2026-05-17 during AI-011-validation): 1. Verification assertion was stale. The check grepped for the literal "Engineering Discipline" in the deployed copilot-instructions.md, but that string no longer exists -- AI-013 refactored the file to a pointer-style ≤70-line shim that delegates to AGENTS.md. The check would fail on every run, printing an "❌ Error" line immediately followed by "[SUCCESS]". Replaced with the same pattern that Claude/Gemini deploys already use: grep for `First, read \`AGENTS.md\``. 2. The block was gated on `gh` being installed, which is the wrong signal -- gh is widely used for PR/issue management without any Copilot intent. On Linux specifically the user does not use Copilot; on Windows it is per-machine. Now gated on the gh-copilot extension being actually installed (detect-and-act): if the extension is present the config deploys and aliases are wired; if absent the block is skipped with an info-level log including the install one-liner. The Linux script also no longer attempts to `gh extension install github/gh-copilot` unconditionally -- that decision is the user's. The detect-and-act pattern lets the script remain "try everything that is already available, warn on missing pieces" without surprise installs. Windows side mirrors the same logic via the gh extension list parse. Verification string updated identically. ASCII-clean (PSScriptAnalyzer non-ASCII gate respected). Empirical Windows verification still pending until WIN-002 runs. --- setup-linux.sh | 44 ++++++++++++++++++++++++++++---------------- setup-windows.ps1 | 45 ++++++++++++++++++++++++++++----------------- 2 files changed, 56 insertions(+), 33 deletions(-) diff --git a/setup-linux.sh b/setup-linux.sh index a174b58..565340a 100755 --- a/setup-linux.sh +++ b/setup-linux.sh @@ -2,6 +2,11 @@ # setup-linux.sh: Install dotfiles and set up environment # Usage: ./setup-linux.sh +# +# Philosophy: opportunistic configuration. The script attempts to set up +# every supported tool and warns when something is not available, rather +# than requiring opt-in flags. Heavy / disk-intensive installs (e.g. +# future Ollama, Ghostty) may add explicit flags case by case. set -euo pipefail @@ -424,26 +429,33 @@ else log_warning "opencode binary not reachable at $OPENCODE_BINARY after install — agent unavailable" fi -# GitHub Copilot CLI (requires gh) +# GitHub Copilot CLI (detect-and-act: deploy config only when the extension +# is actually installed; the script does NOT auto-install the extension on +# Linux — gh is widely used for PR/issue management without Copilot intent. +# To enable: gh extension install github/gh-copilot, then re-run setup). +# Verification string updated for AI-013 pointer-style copilot-instructions.md. if command -v gh >/dev/null 2>&1; then - log_info "Installing GitHub Copilot CLI extension..." - gh extension install github/gh-copilot 2>/dev/null || true - ensure_directory "$HOME/.copilot" - cp -rf "$CURRENT_DIR/ai/copilot/"* "$HOME/.copilot/" 2>/dev/null || true - if [ -f "$HOME/.copilot/copilot-instructions.md" ] && grep -q "Engineering Discipline" "$HOME/.copilot/copilot-instructions.md"; then - log_success "Copilot instructions deployed successfully (verified)" + if gh extension list 2>/dev/null | grep -q "github/gh-copilot"; then + log_info "GitHub Copilot CLI extension detected, deploying configuration..." + ensure_directory "$HOME/.copilot" + cp -rf "$CURRENT_DIR/ai/copilot/"* "$HOME/.copilot/" 2>/dev/null || true + if [ -f "$HOME/.copilot/copilot-instructions.md" ] && grep -q 'First, read `AGENTS.md`' "$HOME/.copilot/copilot-instructions.md"; then + log_success "copilot-instructions.md deployed successfully (verified pointer to AGENTS.md)" + else + log_warning "copilot-instructions.md deployment failed verification (expected pointer to AGENTS.md)" + fi + log_success "GitHub Copilot CLI configured" + + # Aliases + log_info "Adding Copilot aliases to .zshrc/.bashrc..." + COPILOT_SUGGEST='eval "$(gh copilot alias -- bash)"' + [ -f "$HOME/.zshrc" ] && ensure_line_in_file "$HOME/.zshrc" "$COPILOT_SUGGEST" + [ -f "$HOME/.bashrc" ] && ensure_line_in_file "$HOME/.bashrc" "$COPILOT_SUGGEST" else - echo "❌ Error: Copilot instructions deployment failed verification" + log_info "GitHub Copilot CLI extension not installed, skipping Copilot config (install with: gh extension install github/gh-copilot)" fi - log_success "GitHub Copilot CLI configured" - - # Aliases - log_info "Adding Copilot aliases to .zshrc/.bashrc..." - COPILOT_SUGGEST='eval "$(gh copilot alias -- bash)"' - [ -f "$HOME/.zshrc" ] && ensure_line_in_file "$HOME/.zshrc" "$COPILOT_SUGGEST" - [ -f "$HOME/.bashrc" ] && ensure_line_in_file "$HOME/.bashrc" "$COPILOT_SUGGEST" else - log_warning "GitHub CLI (gh) not found, skipping Copilot installation" + log_warning "GitHub CLI (gh) not found, skipping Copilot setup" fi # Register MCP servers (requires Claude Code CLI, Node.js, jq) diff --git a/setup-windows.ps1 b/setup-windows.ps1 index 562d873..4591dc4 100644 --- a/setup-windows.ps1 +++ b/setup-windows.ps1 @@ -792,32 +792,43 @@ if (Test-Path $ClaudeSettings) { Write-Info "Setting up GitHub Copilot CLI..." +# Detect-and-act: deploy config only when gh AND the gh-copilot extension +# are actually installed. The script does NOT auto-install the extension -- +# gh is widely used for PR/issue management on machines that do not want +# Copilot. To enable: gh extension install github/gh-copilot, then re-run. +# Verification string updated for AI-013 pointer-style copilot-instructions.md. $ghCmd = Get-Command gh -ErrorAction SilentlyContinue if ($ghCmd) { - Write-Info "Installing GitHub Copilot CLI extension..." + $copilotInstalled = $false try { - & gh extension install github/gh-copilot 2>$null + $extensions = & gh extension list 2>$null + $copilotInstalled = ($extensions -match 'github/gh-copilot') } catch { - # Extension may already be installed + $copilotInstalled = $false } - $CopilotHome = "$env:USERPROFILE\.copilot" - Ensure-Directory $CopilotHome - - $copilotSource = "$DotfilesDir\ai\copilot" - if (Test-Path $copilotSource) { - Copy-Item "$copilotSource\*" "$CopilotHome\" -Recurse -Force -ErrorAction SilentlyContinue - if ((Test-Path "$CopilotHome\copilot-instructions.md") -and - (Select-String -Path "$CopilotHome\copilot-instructions.md" -Pattern "Engineering Discipline" -Quiet)) { - Write-Success "Copilot instructions deployed successfully (verified)" - } else { - Write-Err "Copilot instructions deployment failed verification" + if ($copilotInstalled) { + Write-Info "GitHub Copilot CLI extension detected, deploying configuration..." + $CopilotHome = "$env:USERPROFILE\.copilot" + Ensure-Directory $CopilotHome + + $copilotSource = "$DotfilesDir\ai\copilot" + if (Test-Path $copilotSource) { + Copy-Item "$copilotSource\*" "$CopilotHome\" -Recurse -Force -ErrorAction SilentlyContinue + if ((Test-Path "$CopilotHome\copilot-instructions.md") -and + (Select-String -Path "$CopilotHome\copilot-instructions.md" -Pattern 'First, read `AGENTS.md`' -SimpleMatch -Quiet)) { + Write-Success "copilot-instructions.md deployed successfully (verified pointer to AGENTS.md)" + } else { + Write-Warn "copilot-instructions.md deployment failed verification (expected pointer to AGENTS.md)" + } } - } - Write-Success "GitHub Copilot CLI configured (aliases ghcs/ghce in profile.ps1)" + Write-Success "GitHub Copilot CLI configured (aliases ghcs/ghce in profile.ps1)" + } else { + Write-Info "GitHub Copilot CLI extension not installed, skipping Copilot config (install with: gh extension install github/gh-copilot)" + } } else { - Write-Warn "GitHub CLI (gh) not found, skipping Copilot installation" + Write-Warn "GitHub CLI (gh) not found, skipping Copilot setup" } # Weekly vault maintenance scheduled task (Sundays 10:07 AM) From 5dfed052b7731b491c095f1f72ca441db2b747a7 Mon Sep 17 00:00:00 2001 From: Manu Date: Sun, 17 May 2026 20:37:14 -0600 Subject: [PATCH 2/2] fix(BUG-001): update integration test for detect-and-act Copilot logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit verify-setup.bats line 289 asserted `[ -d "$HOME/.copilot" ]`, encoding the old assumption "if gh is installed, ~/.copilot is unconditionally created". The PR-40 detect-and-act gate breaks that — the directory is now created only when the gh-copilot extension is genuinely present. In the integration container gh is installed (as a dev tool) but gh-copilot is not, so the directory should NOT exist. Inverted the assertion + renamed the test + added a comment block linking the change to the BUG-001 fix and explaining the silent-skip contract. --- tests/verify-setup.bats | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tests/verify-setup.bats b/tests/verify-setup.bats index 455006a..a55e72e 100644 --- a/tests/verify-setup.bats +++ b/tests/verify-setup.bats @@ -285,8 +285,13 @@ setup() { # Section 10: Graceful skips (optional tools not present) # ============================================================================= -@test "copilot directory created (gh installed)" { - [ -d "$HOME/.copilot" ] +@test "copilot config NOT deployed when gh-copilot extension is absent" { + # Post-BUG-001 (PR #40): setup-linux.sh uses detect-and-act. The + # gh-copilot extension is no longer auto-installed; ~/.copilot is created + # only if the extension is genuinely present. In the integration container + # gh is installed (as a dev tool) but gh-copilot is not, so the directory + # should NOT exist — confirming the skip path is silent and correct. + [ ! -d "$HOME/.copilot" ] } @test "no MCP servers registered (claude CLI absent)" {