diff --git a/.ansible-lint b/.ansible-lint new file mode 100644 index 00000000..abab82ca --- /dev/null +++ b/.ansible-lint @@ -0,0 +1,3 @@ +exclude_paths: + - .github/workflows/ + - src/agenttask-templates/ diff --git a/.github/workflows/memory-check.yml b/.github/workflows/memory-check.yml index fc0ee261..d0de03ca 100644 --- a/.github/workflows/memory-check.yml +++ b/.github/workflows/memory-check.yml @@ -11,108 +11,108 @@ jobs: check-memory-files: runs-on: ubuntu-latest name: "🔒 Memory Privacy Protection" - + steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - # Fetch full history for comprehensive checking - fetch-depth: 0 - - - name: Check repository for memory files - run: | - echo "🔍 Scanning repository for memory files..." - - # Check if any memory files are tracked in git - TRACKED_MEMORY=$(git ls-files | grep -E "^memory/|\.memory$|\.learning$" || true) - - if [ ! -z "$TRACKED_MEMORY" ]; then - echo "" - echo "❌ CRITICAL: Memory files found in repository!" - echo "" - echo "📋 Tracked memory files:" - echo "$TRACKED_MEMORY" | sed 's/^/ - /' - echo "" - echo "🔒 These files contain private learning data and violate memory privacy!" - echo "" - echo "🛠️ Immediate action required:" - echo " git rm -r memory/ # Remove from tracking" - echo " git rm *.memory *.learning # Remove memory files" - echo " git commit -m 'Remove memory files from tracking'" - echo "" - echo "ℹ️ Memory files should remain local-only as configured in .gitignore" - exit 1 - fi - - echo "✅ Repository scan complete - no tracked memory files found" - - - name: Check PR diff for memory files (PR only) - if: github.event_name == 'pull_request' - run: | - echo "" - echo "🔍 Checking PR changes for memory files..." - - # Get the target branch (usually main) - TARGET_BRANCH="${{ github.base_ref }}" - - # Check files changed in this PR - CHANGED_MEMORY=$(git diff --name-only origin/$TARGET_BRANCH...HEAD | grep -E "^memory/|\.memory$|\.learning$" || true) - - if [ ! -z "$CHANGED_MEMORY" ]; then + - name: Checkout code + uses: actions/checkout@v4 + with: + # Fetch full history for comprehensive checking + fetch-depth: 0 + + - name: Check repository for memory files + run: | + echo "🔍 Scanning repository for memory files..." + + # Check if any memory files are tracked in git + TRACKED_MEMORY=$(git ls-files | grep -E "^memory/|\.memory$|\.learning$" || true) + + if [ ! -z "$TRACKED_MEMORY" ]; then + echo "" + echo "❌ CRITICAL: Memory files found in repository!" + echo "" + echo "📋 Tracked memory files:" + echo "$TRACKED_MEMORY" | sed 's/^/ - /' + echo "" + echo "🔒 These files contain private learning data and violate memory privacy!" + echo "" + echo "🛠️ Immediate action required:" + echo " git rm -r memory/ # Remove from tracking" + echo " git rm *.memory *.learning # Remove memory files" + echo " git commit -m 'Remove memory files from tracking'" + echo "" + echo "ℹ️ Memory files should remain local-only as configured in .gitignore" + exit 1 + fi + + echo "✅ Repository scan complete - no tracked memory files found" + + - name: Check PR diff for memory files (PR only) + if: github.event_name == 'pull_request' + run: | echo "" - echo "❌ PR BLOCKED: Memory files in pull request!" + echo "🔍 Checking PR changes for memory files..." + + # Get the target branch (usually main) + TARGET_BRANCH="${{ github.base_ref }}" + + # Check files changed in this PR + CHANGED_MEMORY=$(git diff --name-only origin/$TARGET_BRANCH...HEAD | grep -E "^memory/|\.memory$|\.learning$" || true) + + if [ ! -z "$CHANGED_MEMORY" ]; then + echo "" + echo "❌ PR BLOCKED: Memory files in pull request!" + echo "" + echo "📋 Memory files in PR changes:" + echo "$CHANGED_MEMORY" | sed 's/^/ - /' + echo "" + echo "🔒 Memory files must never be included in pull requests." + echo "" + echo "🛠️ To fix this PR:" + echo " git rm --cached memory/ # Remove from staging" + echo " git rm --cached *.memory # Remove memory files" + echo " git rm --cached *.learning # Remove learning files" + echo " git commit -m 'Remove memory files from PR'" + echo " git push # Update PR" + echo "" + exit 1 + fi + + echo "✅ PR diff clean - no memory files in changes" + + - name: Verify .gitignore protection + run: | echo "" - echo "📋 Memory files in PR changes:" - echo "$CHANGED_MEMORY" | sed 's/^/ - /' + echo "🔍 Verifying .gitignore protection for memory files..." + + # Check if memory patterns are properly ignored + if ! grep -q "^memory/" .gitignore; then + echo "⚠️ WARNING: memory/ not found in .gitignore" + fi + + if ! grep -q "\*.memory" .gitignore; then + echo "⚠️ WARNING: *.memory pattern not found in .gitignore" + fi + + if ! grep -q "\*.learning" .gitignore; then + echo "⚠️ WARNING: *.learning pattern not found in .gitignore" + fi + + echo "✅ .gitignore verification complete" + + - name: Security scan summary + run: | echo "" - echo "🔒 Memory files must never be included in pull requests." + echo "🔒 MEMORY PROTECTION SUMMARY" + echo "==============================" + echo "✅ Repository scan: PASSED" + if [ "${{ github.event_name }}" = "pull_request" ]; then + echo "✅ PR diff scan: PASSED" + fi + echo "✅ .gitignore check: COMPLETED" echo "" - echo "🛠️ To fix this PR:" - echo " git rm --cached memory/ # Remove from staging" - echo " git rm --cached *.memory # Remove memory files" - echo " git rm --cached *.learning # Remove learning files" - echo " git commit -m 'Remove memory files from PR'" - echo " git push # Update PR" + echo "🛡️ Multi-layer protection active:" + echo " - .gitignore: Prevents accidental staging" + echo " - Pre-commit hook: Local protection (.githooks/pre-commit)" + echo " - GitHub workflow: CI/CD protection (this check)" echo "" - exit 1 - fi - - echo "✅ PR diff clean - no memory files in changes" - - - name: Verify .gitignore protection - run: | - echo "" - echo "🔍 Verifying .gitignore protection for memory files..." - - # Check if memory patterns are properly ignored - if ! grep -q "^memory/" .gitignore; then - echo "⚠️ WARNING: memory/ not found in .gitignore" - fi - - if ! grep -q "\*.memory" .gitignore; then - echo "⚠️ WARNING: *.memory pattern not found in .gitignore" - fi - - if ! grep -q "\*.learning" .gitignore; then - echo "⚠️ WARNING: *.learning pattern not found in .gitignore" - fi - - echo "✅ .gitignore verification complete" - - - name: Security scan summary - run: | - echo "" - echo "🔒 MEMORY PROTECTION SUMMARY" - echo "==============================" - echo "✅ Repository scan: PASSED" - if [ "${{ github.event_name }}" = "pull_request" ]; then - echo "✅ PR diff scan: PASSED" - fi - echo "✅ .gitignore check: COMPLETED" - echo "" - echo "🛡️ Multi-layer protection active:" - echo " - .gitignore: Prevents accidental staging" - echo " - Pre-commit hook: Local protection (.githooks/pre-commit)" - echo " - GitHub workflow: CI/CD protection (this check)" - echo "" - echo "✅ Memory privacy maintained!" \ No newline at end of file + echo "✅ Memory privacy maintained!" diff --git a/.gitignore b/.gitignore index c3e9c2b6..a36b3fb5 100644 --- a/.gitignore +++ b/.gitignore @@ -97,3 +97,6 @@ credentials/ secrets/memory/ stories/ bugs/ + +# Local summaries and reports +summaries/ diff --git a/ARCHITECTURAL_FAILURE_DIAGNOSIS.md b/ARCHITECTURAL_FAILURE_DIAGNOSIS.md deleted file mode 100644 index cb938842..00000000 --- a/ARCHITECTURAL_FAILURE_DIAGNOSIS.md +++ /dev/null @@ -1,208 +0,0 @@ -# Architectural Failure Diagnosis: Behavioral Enforcement System - -**Note:** This document describes legacy v8-era enforcement issues. v9 removes most enforcement hooks and keeps only minimal safety/privacy hooks. See `docs/hook-system-guide.md` for current behavior. - -## Executive Summary - -**CRITICAL FINDING**: The intelligent-claude-code system lacks actual enforcement mechanisms for its behavioral patterns. The core issue is **architectural**, not configurational - behavioral patterns are advisory text that Claude can override, leading to consistent violations of the AgentTask→Agent delegation pattern. - -## Root Cause Analysis - -### 1. Advisory vs. Mandatory Pattern Architecture - -**Problem**: Behavioral patterns exist as markdown files with strong language ("NUCLEAR BLOCKING", "MANDATORY") but have no enforcement mechanism. - -**Evidence**: -- Memory pattern `comprehensive-enforcement-analysis.md`: "Even the most aggressive 'NUCLEAR BLOCKING' language has the same weight as 'please consider'" -- System continues executing work directly in main scope despite loaded behavioral patterns -- PM role performs technical work despite "ABSOLUTELY FORBIDDEN" patterns - -### 2. Removed Enforcement Infrastructure - -**Critical Discovery**: PreToolUse/PostToolUse hooks that could provide real blocking were **intentionally removed**. - -**From CHANGELOG**: -``` -- Removed Obsolete Hooks: Eliminated SessionStart, PreToolUse, PostToolUse hooks entirely -``` - -**Current Architecture**: Only UserPromptSubmit hooks provide guidance but cannot block tool execution. - -### 3. Helpfulness Override Pattern - -**Root Behavioral Issue**: Claude's core directive to be helpful overrides architectural compliance when they conflict. - -**Pattern**: -1. User requests work: "Fix the authentication bug" -2. UserPromptSubmit adds guidance: "NO WORK IN MAIN SCOPE" -3. Claude decides: User needs help → Direct execution proceeds -4. Architectural pattern violated despite loaded behavioral context - -## Technical Analysis - -### Current Hook Architecture - -**What Works**: -- UserPromptSubmit: Provides context-aware guidance before responses -- Detects work patterns, @Role mentions, memory requirements -- Educational reminders and system initialization detection - -**What Fails**: -- No tool interception capability -- Cannot block Edit/Write/MultiEdit operations -- Behavioral patterns remain "suggestions" during execution - -### Missing Enforcement Layer - -**Required Components**: -```bash -PreToolUse Hooks: -├── Intercept tool execution attempts -├── Analyze context (main vs agent scope) -├── Apply blocking rules for violations -└── Return deny/allow with clear messages -``` - -**Proven Pattern** (from claude-code-tamagotchi): -```json -{ - "hooks": { - "PreToolUse": [{ - "matcher": "*", - "hooks": [{ - "type": "command", - "command": "bunx violation-check" - }] - }] - } -} -``` - -## Specific Failures Documented - -### 1. Main Scope Work Execution -- **Pattern**: `work-detection-patterns.md` with "ULTRA-STRICT" detection -- **Reality**: Main scope continues Edit/Write operations -- **Impact**: Architecture violated, work not tracked in AgentTasks - -### 2. PM Role Technical Work -- **Pattern**: `pm-role-blocking-patterns.md` with "NUCLEAR BLOCKING" -- **Reality**: PM role uses Edit tools when perceived as helpful -- **Impact**: Role separation compromised - -### 3. AgentTask Bypass -- **Pattern**: `agenttask-enforcement.md` requires AgentTask for all work -- **Reality**: Nano/tiny work executed directly without AgentTasks -- **Impact**: Work tracking and delegation patterns broken - -## Solution Architecture - -### Phase 1: Restore PreToolUse Enforcement - -**Implementation**: -```javascript -// Hook analyzes tool usage attempt -const violation = checkViolation(tool, parameters, context); - -if (violation.blocked) { - return { - permissionDecision: "deny", - permissionDecisionReason: violation.reason - }; -} -``` - -**Core Rules**: -1. Block Edit/Write/MultiEdit in main scope for complexity >2 points -2. Block all technical tools for PM role -3. Require AgentTask context for medium+ complexity work - -### Phase 2: Auto-AgentTask Generation - -**Enhancement**: Violations trigger automatic AgentTask creation -``` -❌ BLOCKED: Main scope Edit operation -📋 AgentTask created: agenttasks/ready/AgentTask-003-fix-auth.yaml -🚀 Deploy with: Task tool → @Developer -``` - -## Implementation Plan - -### Days 1-2: Critical Blocking Infrastructure -- Restore PreToolUse hook with basic violation detection -- Implement main scope work blocking -- Add PM role technical tool restrictions - -### Days 3-4: Installation Integration -- Update Windows PowerShell installer -- Update Ansible deployment scripts -- Comprehensive testing and validation - -### Days 5-7: Auto-Generation Enhancement -- AgentTask creation from violations -- Complete context embedding -- Seamless user workflow - -## Expected Outcomes - -### Behavioral Compliance -- **Current**: ~30% compliance with AgentTask patterns -- **Target**: >95% compliance with real enforcement -- **Method**: Tool usage blocked until proper delegation - -### User Experience -- **Improvement**: Clear error messages with guidance -- **Enhancement**: Auto-generated AgentTasks reduce friction -- **Consistency**: Predictable enforcement across all contexts - -## Critical Success Factors - -1. **Real Blocking**: PreToolUse hooks can actually prevent violations -2. **Clear Guidance**: Error messages explain proper patterns -3. **Auto-Generation**: Violations create ready-to-deploy AgentTasks -4. **Fail-Open Design**: System continues working if hooks fail -5. **Gradual Rollout**: Validation before full deployment - -## Conclusion - -The intelligent-claude-code behavioral enforcement failure is **fundamental and architectural**. Advisory patterns cannot overcome Claude's helpfulness directive. Only external enforcement through PreToolUse hooks can provide actual behavioral compliance. - -**Immediate Action Required**: Implement Phase 1 blocking infrastructure to establish architectural integrity before optimizing behavioral patterns. - -**Success Model**: Follow claude-code-tamagotchi pattern with exit-code-based blocking for proven enforcement capability. - ---- - -## Files Created - -### Memory Patterns -- `/memory/behavioral-enforcement/architectural-failure-analysis.md` - Comprehensive root cause analysis -- `/memory/behavioral-enforcement/enforcement-solution-architecture.md` - Complete solution design -- `/memory/behavioral-enforcement/immediate-implementation-plan.md` - Detailed implementation plan - -### Analysis Documents -- `ARCHITECTURAL_FAILURE_DIAGNOSIS.md` - Executive summary and findings (this file) - -## Relevant Files Analyzed - -### Behavioral Patterns -- `src/behaviors/agenttask-enforcement.md` - Current enforcement patterns -- `src/behaviors/shared-patterns/work-detection-patterns.md` - Work detection logic -- `src/behaviors/shared-patterns/pm-role-blocking-patterns.md` - PM role restrictions - -### Memory Patterns -- `memory/behavioral-enforcement/comprehensive-enforcement-analysis.md` - Previous analysis -- `memory/behavioral-enforcement/pattern-enforcement-limitations.md` - Known limitations -- `memory/system/behavioral-violations.md` - Documented violations - -### Hook System -- `src/hooks/user-prompt-submit.js` - Current guidance system -- `memory/architecture/optimal-hook-architecture.md` - Hook removal rationale - -### Best Practices -- `best-practices-examples/git/feature-branch-workflow.md` - Implementation standards -- `best-practices-examples/architecture/configuration-first-design.md` - Design principles - ---- -*Diagnosis completed 2025-01-21 by @AI-Engineer* -*Comprehensive analysis with immediate implementation plan ready* diff --git a/CHANGELOG.md b/CHANGELOG.md index ddb5fa44..cd140ed1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -113,7 +113,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ALL-CAPS filename enforcement retains execution-pattern guidance while auto-suggesting lowercase/kebab alternatives. ### Changed -- All sample configs now force best-practices/constraints output and keep memory integration plus git branch protection enabled. +- All sample configs now force constraints output and keep memory integration plus git branch protection enabled. - Main-scope coordination whitelist can be extended via `enforcement.main_scope_allowed_bash_commands` so presets can safely allow additional `gh`/`git` commands. - README highlights the available presets for quick reference. - Context-injection now instructs the Main Scope to start every response with the rendered constraints + best-practice block so users see the guardrails continuously. diff --git a/Makefile b/Makefile index 63b9d869..2699c595 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,7 @@ help: @echo " HOST - Remote host IP (omit for local installation)" @echo " USER - Remote username (required for remote installation)" @echo " TARGET_PATH - Target path (omit for user scope ~/.claude/)" - @echo " CONFIG_FILE - Path to icc.config JSON to deploy (default icc.config.default.json)" + @echo " CONFIG_FILE - Path to icc.config JSON to deploy (optional)" @echo " MCP_CONFIG - Path to MCP servers configuration JSON file" @echo " ENV_FILE - Path to .env file with environment variables" @echo " KEY - SSH key for remote (default: ~/.ssh/id_rsa)" diff --git a/README.md b/README.md index e14571bb..2accd8d4 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,14 @@ # Intelligent Claude Code -CC‑native framework for planning‑first AgentTasks, native subagents, and minimal hooks. +CC‑native framework slimmed to what Claude Code 2 + Opus still needs. ## Current scope (v9) -- **CC‑native subagents** — no marker files, no custom role enforcement hooks. +- **Claude Code 2 + Opus focused** — keep only what CC doesn’t do natively. +- **CC‑native subagents** — no marker files or custom role‑enforcement hooks. - **Planning‑first AgentTasks** — main scope plans, subagents implement. -- **Minimal hooks only** — keep only what CC doesn’t do natively. -- **Behavior guidance** — behaviors live in the repo and are read by humans + Claude. +- **Minimal hooks** — privacy, infra safety, summary/report routing. +- **Behavior guidance** — behaviors live in the repo and guide humans + Claude. ## Included @@ -19,14 +20,6 @@ CC‑native framework for planning‑first AgentTasks, native subagents, and min - `agent-infrastructure-protection.js` — block imperative infra changes - `summary-file-enforcement.js` — route summaries/reports + block ALL‑CAPS filenames -## Removed - -- Marker‑based orchestration -- Role enforcement hooks -- Reminder hooks -- Auto‑trigger and workflow hooks -- Redundant behavior trees - ## Principles 1. **Plan first** → create AgentTask before implementation. @@ -37,9 +30,9 @@ CC‑native framework for planning‑first AgentTasks, native subagents, and min ## Core roles -@PM, @Architect, @Developer, @System‑Engineer, @DevOps‑Engineer, @Database‑Engineer, -@Security‑Engineer, @AI‑Engineer, @Web‑Designer, @QA‑Engineer, @Backend‑Tester, -@Requirements‑Engineer, @User‑Role, @Reviewer — plus dynamic specialists (e.g., @React‑Developer). +pm, architect, developer, system‑engineer, devops‑engineer, database‑engineer, +security‑engineer, ai‑engineer, web‑designer, qa‑engineer, backend‑tester, +requirements‑engineer, user‑role, reviewer — plus dynamic specialists (e.g., react‑developer). ## Install @@ -50,15 +43,18 @@ make install # or .\install.ps1 install on Windows make clean-install # force uninstall + reinstall (Linux/macOS) ``` -Usage: +Usage (if your Claude Code build supports @‑mentions, use the file names below): ```bash -@PM break down the story -@Architect review the design -@Developer implement auth -@Reviewer audit for regressions +@pm break down the story +@architect review the design +@developer implement auth +@reviewer audit for regressions ``` +If @‑mentions aren’t supported, just ask in plain language: +“Use the architect subagent to review the design.” + ## Model control (user‑configurable) Claude Code model selection remains user‑controlled. Set it via: diff --git a/ansible/install.yml b/ansible/install.yml index 6e00404a..b0a3f3c7 100644 --- a/ansible/install.yml +++ b/ansible/install.yml @@ -5,34 +5,41 @@ - name: Install Intelligent Claude Code hosts: all - gather_facts: yes + gather_facts: true vars: source_dir: "{{ playbook_dir }}/../src" - + tasks: - name: Determine installation scope and path - set_fact: - target_scope: "{{ 'project' if (target_path | default('')) else 'user' }}" - install_path: "{{ ((target_path | default('')) | realpath) + '/.claude' if (target_path | default('')) else ansible_env.HOME + '/.claude' }}" - project_path: "{{ (target_path | default('')) | realpath if (target_path | default('')) else '' }}" - + ansible.builtin.set_fact: + intelligent_claude_code_target_scope: "{{ 'project' if (target_path | default('')) else 'user' }}" + intelligent_claude_code_install_path: >- + {{ ((target_path | default('')) | realpath) + '/.claude' + if (target_path | default('')) + else ansible_env.HOME + '/.claude' }} + intelligent_claude_code_project_path: >- + {{ (target_path | default('')) | realpath + if (target_path | default('')) + else '' }} + - name: Display installation target - debug: - msg: "Installing to: {{ install_path }}" + ansible.builtin.debug: + msg: "Installing to: {{ intelligent_claude_code_install_path }}" when: ansible_verbosity >= 1 - + - name: Include intelligent_claude_code role - include_role: + ansible.builtin.include_role: name: intelligent_claude_code vars: - claude_install_path: "{{ install_path }}" - claude_project_path: "{{ project_path }}" - claude_scope: "{{ target_scope }}" - claude_config_source: "{{ config_file | default('') }}" + intelligent_claude_code_install_path: "{{ intelligent_claude_code_install_path }}" + intelligent_claude_code_project_path: "{{ intelligent_claude_code_project_path }}" + intelligent_claude_code_scope: "{{ intelligent_claude_code_target_scope }}" + intelligent_claude_code_config_source: "{{ config_file | default('') }}" - name: Install MCP servers if configuration provided - include_role: - name: mcp-integration + ansible.builtin.include_role: + name: mcp_integration vars: - settings_json_path: "{{ ansible_env.HOME }}/.claude.json" + mcp_integration_settings_json_path: "{{ ansible_env.HOME }}/.claude.json" + mcp_integration_config_file: "{{ mcp_config_file | default('') }}" when: (mcp_config_file | default('')) != '' diff --git a/ansible/roles/intelligent_claude_code/tasks/graceful_integration.yml b/ansible/roles/intelligent_claude_code/tasks/graceful_integration.yml index 3c6fedb5..677d5119 100644 --- a/ansible/roles/intelligent_claude_code/tasks/graceful_integration.yml +++ b/ansible/roles/intelligent_claude_code/tasks/graceful_integration.yml @@ -3,7 +3,7 @@ - name: Check existing CLAUDE.md content ansible.builtin.command: - cmd: grep -q "@~/.claude/modes/virtual-team.md" "{{ claude_install_path }}/CLAUDE.md" + cmd: grep -q "@~/.claude/modes/virtual-team.md" "{{ intelligent_claude_code_install_path }}/CLAUDE.md" register: intelligent_claude_code_grep_result failed_when: false changed_when: false @@ -13,7 +13,7 @@ block: - name: Read existing CLAUDE.md content ansible.builtin.slurp: - src: "{{ claude_install_path }}/CLAUDE.md" + src: "{{ intelligent_claude_code_install_path }}/CLAUDE.md" register: intelligent_claude_code_existing_content - name: Create integrated CLAUDE.md @@ -25,7 +25,7 @@ {{ intelligent_claude_code_existing_content.content | b64decode }} - dest: "{{ claude_install_path }}/CLAUDE.md" + dest: "{{ intelligent_claude_code_install_path }}/CLAUDE.md" mode: '0644' - name: Report graceful integration diff --git a/ansible/roles/intelligent_claude_code/tasks/main.yml b/ansible/roles/intelligent_claude_code/tasks/main.yml index fc2a9be7..4b534ecf 100644 --- a/ansible/roles/intelligent_claude_code/tasks/main.yml +++ b/ansible/roles/intelligent_claude_code/tasks/main.yml @@ -3,8 +3,8 @@ - name: Validate installation parameters ansible.builtin.assert: that: - - claude_install_path is defined - - claude_scope in ['user', 'project'] + - intelligent_claude_code_install_path is defined + - intelligent_claude_code_scope in ['user', 'project'] fail_msg: "Invalid installation parameters" - name: Create .claude directory structure ansible.builtin.file: @@ -12,23 +12,23 @@ state: directory mode: '0755' loop: - - "{{ claude_install_path }}" - - "{{ claude_install_path }}/modes" - - "{{ claude_install_path }}/behaviors" - - "{{ claude_install_path }}/commands" - - "{{ claude_install_path }}/roles" - - "{{ claude_install_path }}/agents" - - "{{ claude_install_path }}/agenttask-templates" - - "{{ claude_install_path }}/hooks" - - "{{ claude_install_path }}/logs" + - "{{ intelligent_claude_code_install_path }}" + - "{{ intelligent_claude_code_install_path }}/modes" + - "{{ intelligent_claude_code_install_path }}/behaviors" + - "{{ intelligent_claude_code_install_path }}/commands" + - "{{ intelligent_claude_code_install_path }}/roles" + - "{{ intelligent_claude_code_install_path }}/agents" + - "{{ intelligent_claude_code_install_path }}/agenttask-templates" + - "{{ intelligent_claude_code_install_path }}/hooks" + - "{{ intelligent_claude_code_install_path }}/logs" - name: Check if CLAUDE.md exists ansible.builtin.stat: - path: "{{ claude_install_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_install_path }}/CLAUDE.md" register: intelligent_claude_code_claude_md_exists - name: Backup existing CLAUDE.md if present ansible.builtin.copy: - src: "{{ claude_install_path }}/CLAUDE.md" - dest: "{{ claude_install_path }}/CLAUDE.md.backup" + src: "{{ intelligent_claude_code_install_path }}/CLAUDE.md" + dest: "{{ intelligent_claude_code_install_path }}/CLAUDE.md.backup" remote_src: true mode: '0644' when: intelligent_claude_code_claude_md_exists.stat.exists @@ -38,72 +38,72 @@ - name: Create new CLAUDE.md for fresh installation ansible.builtin.template: src: CLAUDE.md.j2 - dest: "{{ claude_install_path }}/CLAUDE.md" + dest: "{{ intelligent_claude_code_install_path }}/CLAUDE.md" mode: '0644' when: not intelligent_claude_code_claude_md_exists.stat.exists - name: Copy virtual team mode files ansible.builtin.copy: src: "{{ playbook_dir }}/../src/modes/" - dest: "{{ claude_install_path }}/modes/" + dest: "{{ intelligent_claude_code_install_path }}/modes/" mode: '0644' force: true register: intelligent_claude_code_modes_copy_result - name: Display modes preservation notice ansible.builtin.debug: - msg: "Mode files preserved: {{ claude_install_path }}/modes/ already exists - keeping user modifications" + msg: "Mode files preserved: {{ intelligent_claude_code_install_path }}/modes/ already exists - keeping user modifications" when: intelligent_claude_code_modes_copy_result.failed and ansible_verbosity >= 1 - name: Copy behavior files ansible.builtin.copy: src: "{{ playbook_dir }}/../src/behaviors/" - dest: "{{ claude_install_path }}/behaviors/" + dest: "{{ intelligent_claude_code_install_path }}/behaviors/" mode: '0644' force: true register: intelligent_claude_code_behaviors_copy_result - name: Display behaviors preservation notice ansible.builtin.debug: - msg: "Behavior files preserved: {{ claude_install_path }}/behaviors/ already exists - keeping user modifications" + msg: "Behavior files preserved: {{ intelligent_claude_code_install_path }}/behaviors/ already exists - keeping user modifications" when: intelligent_claude_code_behaviors_copy_result.failed and ansible_verbosity >= 1 - name: Copy commands directory ansible.builtin.copy: src: "{{ playbook_dir }}/../src/commands/" - dest: "{{ claude_install_path }}/commands/" + dest: "{{ intelligent_claude_code_install_path }}/commands/" mode: '0644' force: true register: intelligent_claude_code_commands_copy_result - name: Display commands preservation notice ansible.builtin.debug: - msg: "Commands directory preserved: {{ claude_install_path }}/commands/ already exists - keeping user modifications" + msg: "Commands directory preserved: {{ intelligent_claude_code_install_path }}/commands/ already exists - keeping user modifications" when: intelligent_claude_code_commands_copy_result.failed and ansible_verbosity >= 1 - name: Copy roles directory ansible.builtin.copy: src: "{{ playbook_dir }}/../src/roles/" - dest: "{{ claude_install_path }}/roles/" + dest: "{{ intelligent_claude_code_install_path }}/roles/" mode: '0644' force: true register: intelligent_claude_code_roles_copy_result - name: Display roles preservation notice ansible.builtin.debug: msg: >- - Roles directory preserved: {{ claude_install_path }}/roles/ + Roles directory preserved: {{ intelligent_claude_code_install_path }}/roles/ already exists - keeping user modifications when: intelligent_claude_code_roles_copy_result.failed and ansible_verbosity >= 1 - name: Copy agents directory ansible.builtin.copy: src: "{{ playbook_dir }}/../src/agents/" - dest: "{{ claude_install_path }}/agents/" + dest: "{{ intelligent_claude_code_install_path }}/agents/" mode: '0644' force: true register: intelligent_claude_code_agents_copy_result - name: Display agents preservation notice ansible.builtin.debug: msg: >- - Agents directory preserved: {{ claude_install_path }}/agents/ + Agents directory preserved: {{ intelligent_claude_code_install_path }}/agents/ already exists - keeping user modifications when: intelligent_claude_code_agents_copy_result.failed and ansible_verbosity >= 1 - name: Copy AgentTask templates directory ansible.builtin.copy: src: "{{ playbook_dir }}/../src/agenttask-templates/" - dest: "{{ claude_install_path }}/agenttask-templates/" + dest: "{{ intelligent_claude_code_install_path }}/agenttask-templates/" mode: '0644' force: true register: intelligent_claude_code_agenttask_templates_copy_result @@ -111,13 +111,13 @@ ansible.builtin.debug: msg: >- AgentTask templates directory preserved: - {{ claude_install_path }}/agenttask-templates/ + {{ intelligent_claude_code_install_path }}/agenttask-templates/ already exists - keeping user modifications when: intelligent_claude_code_agenttask_templates_copy_result.failed and ansible_verbosity >= 1 - name: Copy hooks directory ansible.posix.synchronize: src: "{{ playbook_dir }}/../src/hooks/" - dest: "{{ claude_install_path }}/hooks/" + dest: "{{ intelligent_claude_code_install_path }}/hooks/" recursive: true delete: true rsync_opts: @@ -128,7 +128,7 @@ - name: Ensure hooks subdirectories are copied ansible.builtin.copy: src: "{{ playbook_dir }}/../src/hooks/{{ item }}/" - dest: "{{ claude_install_path }}/hooks/{{ item }}/" + dest: "{{ intelligent_claude_code_install_path }}/hooks/{{ item }}/" mode: preserve force: true loop: @@ -137,12 +137,12 @@ - name: Display hooks preservation notice ansible.builtin.debug: msg: >- - Hooks directory preserved: {{ claude_install_path }}/hooks/ + Hooks directory preserved: {{ intelligent_claude_code_install_path }}/hooks/ already exists - keeping user modifications when: intelligent_claude_code_hooks_copy_result.failed and ansible_verbosity >= 1 - name: Make all hook scripts executable ansible.builtin.file: - path: "{{ claude_install_path }}/hooks/{{ item }}" + path: "{{ intelligent_claude_code_install_path }}/hooks/{{ item }}" mode: '0755' state: file loop: @@ -153,103 +153,63 @@ - name: Copy VERSION file ansible.builtin.copy: src: "{{ playbook_dir }}/../src/VERSION" - dest: "{{ claude_install_path }}/VERSION" + dest: "{{ intelligent_claude_code_install_path }}/VERSION" mode: '0644' force: true register: intelligent_claude_code_version_copy_result - name: Display VERSION preservation notice ansible.builtin.debug: msg: >- - VERSION file preserved: {{ claude_install_path }}/VERSION already exists + VERSION file preserved: {{ intelligent_claude_code_install_path }}/VERSION already exists - keeping user modifications when: intelligent_claude_code_version_copy_result.failed and ansible_verbosity >= 1 -- name: Check if config.md exists - ansible.builtin.stat: - path: "{{ claude_install_path }}/config.md" - register: intelligent_claude_code_config_md_exists - name: Ensure hooks lib directory exists ansible.builtin.file: - path: "{{ claude_install_path }}/hooks/lib" + path: "{{ intelligent_claude_code_install_path }}/hooks/lib" state: directory mode: '0755' -- name: Create config.md from template (ONLY if not exists) - ansible.builtin.copy: - src: "{{ playbook_dir }}/../src/config.md" - dest: "{{ claude_install_path }}/config.md" - mode: '0644' - when: not intelligent_claude_code_config_md_exists.stat.exists -- name: Display config preservation notice - ansible.builtin.debug: - msg: >- - Config file preserved: {{ claude_install_path }}/config.md already exists - - keeping user settings - when: - - intelligent_claude_code_config_md_exists.stat.exists - - ansible_verbosity >= 1 -- name: Copy configuration file (selected or default without overwriting user edits) +- name: Copy configuration file (selected without overwriting user edits) block: - name: Use provided config_file when specified (overwrite) ansible.builtin.copy: - src: "{{ claude_config_source }}" - dest: "{{ claude_install_path }}/icc.config.json" + src: "{{ intelligent_claude_code_config_source }}" + dest: "{{ intelligent_claude_code_install_path }}/icc.config.json" mode: '0644' force: true - when: claude_config_source | length > 0 + when: intelligent_claude_code_config_source | length > 0 - name: Check existing icc.config.json ansible.builtin.stat: - path: "{{ claude_install_path }}/icc.config.json" + path: "{{ intelligent_claude_code_install_path }}/icc.config.json" register: intelligent_claude_code_icc_config_exists - when: claude_config_source | length == 0 + when: intelligent_claude_code_config_source | length == 0 - name: Preserve existing icc.config.json (no config_file supplied) ansible.builtin.debug: msg: "Existing icc.config.json detected – leaving it untouched (pass CONFIG_FILE to override)." when: - - claude_config_source | length == 0 + - intelligent_claude_code_config_source | length == 0 - intelligent_claude_code_icc_config_exists.stat.exists - ansible_verbosity >= 1 - - name: Install default icc.config.json only if missing - ansible.builtin.copy: - src: "{{ playbook_dir }}/../icc.config.default.json" - dest: "{{ claude_install_path }}/icc.config.json" - mode: '0644' - force: false + - name: Note missing icc.config.json when none supplied + ansible.builtin.debug: + msg: "No icc.config.json provided; defaults remain internal (pass CONFIG_FILE to install)." when: - - claude_config_source | length == 0 + - intelligent_claude_code_config_source | length == 0 - not intelligent_claude_code_icc_config_exists.stat.exists - - name: Always install default for reference - ansible.builtin.copy: - src: "{{ playbook_dir }}/../icc.config.default.json" - dest: "{{ claude_install_path }}/icc.config.default.json" - mode: '0644' - force: true + - ansible_verbosity >= 1 - name: Display config installation choice ansible.builtin.debug: msg: >- - Configuration installed or preserved at {{ claude_install_path }}/icc.config.json - (source={{ claude_config_source | default('existing or icc.config.default.json') }}) + Configuration installed or preserved at {{ intelligent_claude_code_install_path }}/icc.config.json + (source={{ intelligent_claude_code_config_source | default('existing') }}) when: ansible_verbosity >= 1 -- name: Copy default workflow configuration file (JSON format) - ansible.builtin.copy: - src: "{{ playbook_dir }}/../icc.workflow.default.json" - dest: "{{ claude_install_path }}/icc.workflow.default.json" - mode: '0644' - force: true - register: intelligent_claude_code_default_workflow_copy_result -- name: Display default workflow installation notice - ansible.builtin.debug: - msg: >- - Default workflow configuration installed: - {{ claude_install_path }}/icc.workflow.default.json - - complete workflow settings available - when: ansible_verbosity >= 1 - name: Check if settings.json exists ansible.builtin.stat: - path: "{{ claude_install_path }}/settings.json" + path: "{{ intelligent_claude_code_install_path }}/settings.json" register: intelligent_claude_code_settings_json_exists - name: Create settings.json with hook registration (ONLY if not exists) ansible.builtin.template: src: settings.json.j2 - dest: "{{ claude_install_path }}/settings.json" + dest: "{{ intelligent_claude_code_install_path }}/settings.json" mode: '0644' when: not intelligent_claude_code_settings_json_exists.stat.exists - name: Merge hooks into existing settings.json @@ -257,7 +217,7 @@ block: - name: Read existing settings.json ansible.builtin.slurp: - src: "{{ claude_install_path }}/settings.json" + src: "{{ intelligent_claude_code_install_path }}/settings.json" register: intelligent_claude_code_existing_settings - name: Parse existing settings as JSON ansible.builtin.set_fact: @@ -279,16 +239,16 @@ - matcher: "*" hooks: - type: command - command: "node {{ claude_install_path }}/hooks/git-enforcement.js" + command: "node {{ intelligent_claude_code_install_path }}/hooks/git-enforcement.js" timeout: 5000 - type: command command: >- - node {{ claude_install_path + node {{ intelligent_claude_code_install_path }}/hooks/agent-infrastructure-protection.js timeout: 5000 - type: command command: >- - node {{ claude_install_path + node {{ intelligent_claude_code_install_path }}/hooks/summary-file-enforcement.js timeout: 5000 - name: Merge production hooks with cleaned hooks @@ -301,7 +261,7 @@ - name: Write merged settings.json ansible.builtin.copy: content: "{{ intelligent_claude_code_merged_settings | to_nice_json(indent=2) }}" - dest: "{{ claude_install_path }}/settings.json" + dest: "{{ intelligent_claude_code_install_path }}/settings.json" mode: '0644' - name: Report hook registration ansible.builtin.debug: @@ -320,12 +280,12 @@ # learning-callouts.md file removed - integrated into learning-team-automation.md system - name: Handle project-specific integration ansible.builtin.import_tasks: project_integration.yml - when: claude_scope == "project" + when: intelligent_claude_code_scope == "project" - name: Display installation summary ansible.builtin.debug: msg: - "✅ Installation complete!" - - "📍 Location: {{ claude_install_path }}" + - "📍 Location: {{ intelligent_claude_code_install_path }}" - "🤖 Virtual Team: 14 core roles + unlimited specialists" - "🔒 Behavioral Hooks: PreToolUse (git, infra protection, summaries)" - "🚀 Use @Role communication to activate team members" diff --git a/ansible/roles/intelligent_claude_code/tasks/project_integration.yml b/ansible/roles/intelligent_claude_code/tasks/project_integration.yml index 0f7a77dc..14636979 100644 --- a/ansible/roles/intelligent_claude_code/tasks/project_integration.yml +++ b/ansible/roles/intelligent_claude_code/tasks/project_integration.yml @@ -2,12 +2,12 @@ # Project-specific integration tasks - name: Check if project CLAUDE.md exists ansible.builtin.stat: - path: "{{ claude_project_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_project_path }}/CLAUDE.md" register: intelligent_claude_code_project_claude_md - name: Backup project CLAUDE.md if exists ansible.builtin.copy: - src: "{{ claude_project_path }}/CLAUDE.md" - dest: "{{ claude_project_path }}/CLAUDE.md.backup" + src: "{{ intelligent_claude_code_project_path }}/CLAUDE.md" + dest: "{{ intelligent_claude_code_project_path }}/CLAUDE.md.backup" remote_src: true mode: '0644' when: intelligent_claude_code_project_claude_md.stat.exists @@ -17,7 +17,7 @@ # Virtual Development Team @~/.claude/modes/virtual-team.md - dest: "{{ claude_project_path }}/CLAUDE.md" + dest: "{{ intelligent_claude_code_project_path }}/CLAUDE.md" mode: '0644' when: not intelligent_claude_code_project_claude_md.stat.exists - name: Integrate with existing project CLAUDE.md @@ -25,13 +25,13 @@ block: - name: Check if import already present in project CLAUDE.md ansible.builtin.command: - cmd: grep -q "@~/.claude/modes/virtual-team.md" "{{ claude_project_path }}/CLAUDE.md" + cmd: grep -q "@~/.claude/modes/virtual-team.md" "{{ intelligent_claude_code_project_path }}/CLAUDE.md" register: intelligent_claude_code_project_import_grep failed_when: false changed_when: false - name: Ensure project CLAUDE.md includes import block ansible.builtin.blockinfile: - path: "{{ claude_project_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_project_path }}/CLAUDE.md" marker: "" block: | # Virtual Development Team diff --git a/ansible/roles/intelligent_claude_code/templates/settings.json.j2 b/ansible/roles/intelligent_claude_code/templates/settings.json.j2 index 2df0da6a..450af194 100644 --- a/ansible/roles/intelligent_claude_code/templates/settings.json.j2 +++ b/ansible/roles/intelligent_claude_code/templates/settings.json.j2 @@ -4,15 +4,15 @@ "matcher": "*", "hooks": [{ "type": "command", - "command": "node {{ claude_install_path }}/hooks/git-enforcement.js", + "command": "node {{ intelligent_claude_code_install_path }}/hooks/git-enforcement.js", "timeout": 5000 }, { "type": "command", - "command": "node {{ claude_install_path }}/hooks/agent-infrastructure-protection.js", + "command": "node {{ intelligent_claude_code_install_path }}/hooks/agent-infrastructure-protection.js", "timeout": 5000 }, { "type": "command", - "command": "node {{ claude_install_path }}/hooks/summary-file-enforcement.js", + "command": "node {{ intelligent_claude_code_install_path }}/hooks/summary-file-enforcement.js", "timeout": 5000 }] }] diff --git a/ansible/roles/intelligent_claude_code_uninstall/tasks/backup_installation.yml b/ansible/roles/intelligent_claude_code_uninstall/tasks/backup_installation.yml index 81ac9ea6..bbb996c2 100644 --- a/ansible/roles/intelligent_claude_code_uninstall/tasks/backup_installation.yml +++ b/ansible/roles/intelligent_claude_code_uninstall/tasks/backup_installation.yml @@ -16,7 +16,7 @@ mode: '0755' - name: Copy entire .claude directory to backup ansible.builtin.copy: - src: "{{ claude_install_path }}/" + src: "{{ intelligent_claude_code_uninstall_install_path }}/" dest: "{{ intelligent_claude_code_uninstall_backup_path }}/" remote_src: true mode: preserve @@ -33,7 +33,7 @@ content: | Intelligent Claude Code - Installation Backup Created: {{ ansible_date_time.iso8601 }} - Original Path: {{ claude_install_path }} + Original Path: {{ intelligent_claude_code_uninstall_install_path }} Backup Path: {{ intelligent_claude_code_uninstall_backup_path }} Host: {{ ansible_hostname }} User: {{ ansible_user_id }} @@ -41,12 +41,11 @@ - CLAUDE.md (main configuration) - modes/ (virtual team mode files) - behaviors/ (behavioral intelligence modules) - - config.md (user configuration) - scores.md (team scoring data) - learning-callouts.md (team learning data) - VERSION (system version) To restore this installation: - 1. Copy contents back to {{ claude_install_path }} + 1. Copy contents back to {{ intelligent_claude_code_uninstall_install_path }} 2. Ensure proper file permissions (644 for files, 755 for directories) 3. Verify import paths in CLAUDE.md match your current setup Backup created by: ansible/uninstall.yml diff --git a/ansible/roles/intelligent_claude_code_uninstall/tasks/graceful_removal.yml b/ansible/roles/intelligent_claude_code_uninstall/tasks/graceful_removal.yml index fb8ec245..aa528db1 100644 --- a/ansible/roles/intelligent_claude_code_uninstall/tasks/graceful_removal.yml +++ b/ansible/roles/intelligent_claude_code_uninstall/tasks/graceful_removal.yml @@ -2,14 +2,14 @@ # Graceful removal from existing CLAUDE.md - name: Check if CLAUDE.md exists ansible.builtin.stat: - path: "{{ claude_install_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_uninstall_install_path }}/CLAUDE.md" register: intelligent_claude_code_uninstall_claude_md_exists - name: Handle CLAUDE.md removal when: intelligent_claude_code_uninstall_claude_md_exists.stat.exists block: - name: Check if import line exists ansible.builtin.command: - cmd: grep -q "@~/.claude/modes/virtual-team.md" "{{ claude_install_path }}/CLAUDE.md" + cmd: grep -q "@~/.claude/modes/virtual-team.md" "{{ intelligent_claude_code_uninstall_install_path }}/CLAUDE.md" register: intelligent_claude_code_uninstall_import_present failed_when: false changed_when: false @@ -18,23 +18,23 @@ block: - name: Read current CLAUDE.md content ansible.builtin.slurp: - src: "{{ claude_install_path }}/CLAUDE.md" + src: "{{ intelligent_claude_code_uninstall_install_path }}/CLAUDE.md" register: intelligent_claude_code_uninstall_current_content - name: Check if backup exists ansible.builtin.stat: - path: "{{ claude_install_path }}/CLAUDE.md.backup" + path: "{{ intelligent_claude_code_uninstall_install_path }}/CLAUDE.md.backup" register: intelligent_claude_code_uninstall_backup_exists - name: Restore from backup if available ansible.builtin.copy: - src: "{{ claude_install_path }}/CLAUDE.md.backup" - dest: "{{ claude_install_path }}/CLAUDE.md" + src: "{{ intelligent_claude_code_uninstall_install_path }}/CLAUDE.md.backup" + dest: "{{ intelligent_claude_code_uninstall_install_path }}/CLAUDE.md" remote_src: true mode: '0644' when: intelligent_claude_code_uninstall_backup_exists.stat.exists register: intelligent_claude_code_uninstall_backup_restored - name: Remove backup file after restoration ansible.builtin.file: - path: "{{ claude_install_path }}/CLAUDE.md.backup" + path: "{{ intelligent_claude_code_uninstall_install_path }}/CLAUDE.md.backup" state: absent when: intelligent_claude_code_uninstall_backup_exists.stat.exists failed_when: false @@ -43,28 +43,28 @@ block: - name: Remove import line ansible.builtin.lineinfile: - path: "{{ claude_install_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_uninstall_install_path }}/CLAUDE.md" line: "@~/.claude/modes/virtual-team.md" state: absent - name: Remove virtual team header line ansible.builtin.lineinfile: - path: "{{ claude_install_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_uninstall_install_path }}/CLAUDE.md" line: "# Virtual Development Team" state: absent - name: Remove empty preservation comment ansible.builtin.lineinfile: - path: "{{ claude_install_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_uninstall_install_path }}/CLAUDE.md" line: "" state: absent - name: Check if CLAUDE.md is effectively empty ansible.builtin.shell: | set -o pipefail - grep -v '^[[:space:]]*$' "{{ claude_install_path }}/CLAUDE.md" | wc -l + grep -v '^[[:space:]]*$' "{{ intelligent_claude_code_uninstall_install_path }}/CLAUDE.md" | wc -l register: intelligent_claude_code_uninstall_content_lines changed_when: false - name: Remove empty CLAUDE.md file ansible.builtin.file: - path: "{{ claude_install_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_uninstall_install_path }}/CLAUDE.md" state: absent when: intelligent_claude_code_uninstall_content_lines.stdout | int == 0 - name: Report manual removal @@ -84,5 +84,5 @@ when: intelligent_claude_code_uninstall_import_present.rc != 0 - name: Report no CLAUDE.md found ansible.builtin.debug: - msg: "No CLAUDE.md found at {{ claude_install_path }}" + msg: "No CLAUDE.md found at {{ intelligent_claude_code_uninstall_install_path }}" when: not intelligent_claude_code_uninstall_claude_md_exists.stat.exists diff --git a/ansible/roles/intelligent_claude_code_uninstall/tasks/main.yml b/ansible/roles/intelligent_claude_code_uninstall/tasks/main.yml index c79b59e2..6904b040 100644 --- a/ansible/roles/intelligent_claude_code_uninstall/tasks/main.yml +++ b/ansible/roles/intelligent_claude_code_uninstall/tasks/main.yml @@ -3,28 +3,28 @@ - name: Validate uninstall parameters ansible.builtin.assert: that: - - claude_install_path is defined - - claude_scope in ['user', 'project'] + - intelligent_claude_code_uninstall_install_path is defined + - intelligent_claude_code_uninstall_scope in ['user', 'project'] fail_msg: "Invalid uninstall parameters" - name: Check if installation exists ansible.builtin.stat: - path: "{{ claude_install_path }}" + path: "{{ intelligent_claude_code_uninstall_install_path }}" register: intelligent_claude_code_uninstall_install_directory - name: Display uninstall mode ansible.builtin.debug: msg: >- Uninstall mode: {{ 'Force removal (all files)' - if (force_remove is defined and force_remove | bool) + if (intelligent_claude_code_uninstall_force_remove is defined and intelligent_claude_code_uninstall_force_remove | bool) else 'Conservative (preserve user data)' }} - name: Handle project-specific removal ansible.builtin.include_tasks: project_removal.yml - when: claude_scope == "project" + when: intelligent_claude_code_uninstall_scope == "project" - name: Handle graceful removal from user CLAUDE.md ansible.builtin.include_tasks: graceful_removal.yml when: intelligent_claude_code_uninstall_install_directory.stat.exists - name: Remove system files (modes directory) ansible.builtin.file: - path: "{{ claude_install_path }}/modes" + path: "{{ intelligent_claude_code_uninstall_install_path }}/modes" state: absent failed_when: false register: intelligent_claude_code_uninstall_modes_removal @@ -40,7 +40,7 @@ when: intelligent_claude_code_uninstall_install_directory.stat.exists - name: Remove system files (behaviors directory) ansible.builtin.file: - path: "{{ claude_install_path }}/behaviors" + path: "{{ intelligent_claude_code_uninstall_install_path }}/behaviors" state: absent failed_when: false register: intelligent_claude_code_uninstall_behaviors_removal @@ -56,7 +56,7 @@ when: intelligent_claude_code_uninstall_install_directory.stat.exists - name: Remove system files (commands directory) ansible.builtin.file: - path: "{{ claude_install_path }}/commands" + path: "{{ intelligent_claude_code_uninstall_install_path }}/commands" state: absent failed_when: false register: intelligent_claude_code_uninstall_commands_removal @@ -72,7 +72,7 @@ when: intelligent_claude_code_uninstall_install_directory.stat.exists - name: Remove system files (roles directory) ansible.builtin.file: - path: "{{ claude_install_path }}/roles" + path: "{{ intelligent_claude_code_uninstall_install_path }}/roles" state: absent failed_when: false register: intelligent_claude_code_uninstall_roles_removal @@ -88,7 +88,7 @@ when: intelligent_claude_code_uninstall_install_directory.stat.exists - name: Remove system files (agents directory) ansible.builtin.file: - path: "{{ claude_install_path }}/agents" + path: "{{ intelligent_claude_code_uninstall_install_path }}/agents" state: absent failed_when: false register: intelligent_claude_code_uninstall_agents_removal @@ -104,7 +104,7 @@ when: intelligent_claude_code_uninstall_install_directory.stat.exists - name: Remove system files (agenttask-templates directory) ansible.builtin.file: - path: "{{ claude_install_path }}/agenttask-templates" + path: "{{ intelligent_claude_code_uninstall_install_path }}/agenttask-templates" state: absent failed_when: false register: intelligent_claude_code_uninstall_agenttask_templates_removal @@ -120,7 +120,7 @@ when: intelligent_claude_code_uninstall_install_directory.stat.exists - name: Remove system files (VERSION file) ansible.builtin.file: - path: "{{ claude_install_path }}/VERSION" + path: "{{ intelligent_claude_code_uninstall_install_path }}/VERSION" state: absent failed_when: false register: intelligent_claude_code_uninstall_version_removal @@ -140,36 +140,35 @@ state: absent failed_when: false loop: - - "{{ claude_install_path }}/config.md" - - "{{ claude_install_path }}/scores.md" - - "{{ claude_install_path }}/learning-callouts.md" + - "{{ intelligent_claude_code_uninstall_install_path }}/scores.md" + - "{{ intelligent_claude_code_uninstall_install_path }}/learning-callouts.md" register: intelligent_claude_code_uninstall_user_data_removal when: - intelligent_claude_code_uninstall_install_directory.stat.exists - - force_remove is defined and force_remove | bool + - intelligent_claude_code_uninstall_force_remove is defined and intelligent_claude_code_uninstall_force_remove | bool - name: Display user data removal result ansible.builtin.debug: msg: "User data files removed (force mode)" when: - intelligent_claude_code_uninstall_install_directory.stat.exists - - force_remove is defined and force_remove | bool + - intelligent_claude_code_uninstall_force_remove is defined and intelligent_claude_code_uninstall_force_remove | bool - name: Display user data preservation notice ansible.builtin.debug: msg: >- - User data preserved: config.md, scores.md, learning-callouts.md + User data preserved: scores.md, learning-callouts.md (use FORCE=true to remove) when: - intelligent_claude_code_uninstall_install_directory.stat.exists - - not (force_remove is defined and force_remove | bool) + - not (intelligent_claude_code_uninstall_force_remove is defined and intelligent_claude_code_uninstall_force_remove | bool) - name: Check if .claude directory is empty ansible.builtin.find: - paths: "{{ claude_install_path }}" + paths: "{{ intelligent_claude_code_uninstall_install_path }}" file_type: any register: intelligent_claude_code_uninstall_claude_dir_contents when: intelligent_claude_code_uninstall_install_directory.stat.exists - name: Remove empty .claude directory ansible.builtin.file: - path: "{{ claude_install_path }}" + path: "{{ intelligent_claude_code_uninstall_install_path }}" state: absent failed_when: false register: intelligent_claude_code_uninstall_claude_dir_removal @@ -186,13 +185,13 @@ when: intelligent_claude_code_uninstall_install_directory.stat.exists - name: Force remove .claude directory (force mode only) ansible.builtin.file: - path: "{{ claude_install_path }}" + path: "{{ intelligent_claude_code_uninstall_install_path }}" state: absent failed_when: false register: intelligent_claude_code_uninstall_claude_dir_force_removal when: - intelligent_claude_code_uninstall_install_directory.stat.exists - - force_remove is defined and force_remove | bool + - intelligent_claude_code_uninstall_force_remove is defined and intelligent_claude_code_uninstall_force_remove | bool - intelligent_claude_code_uninstall_claude_dir_contents.matched > 0 - name: Display force removal result ansible.builtin.debug: @@ -204,31 +203,31 @@ | default('Permission denied')) }} when: - intelligent_claude_code_uninstall_install_directory.stat.exists - - force_remove is defined and force_remove | bool + - intelligent_claude_code_uninstall_force_remove is defined and intelligent_claude_code_uninstall_force_remove | bool - intelligent_claude_code_uninstall_claude_dir_contents.matched > 0 - name: Display uninstall summary ansible.builtin.debug: msg: - "Uninstall complete!" - - "Location: {{ claude_install_path }}" + - "Location: {{ intelligent_claude_code_uninstall_install_path }}" - >- Mode: {{ 'Force removal - all files removed' - if (force_remove is defined and force_remove | bool) + if (intelligent_claude_code_uninstall_force_remove is defined and intelligent_claude_code_uninstall_force_remove | bool) else 'Conservative - user data preserved' }} - >- Removed: Virtual team modes, behaviors, commands, roles, agents, agenttask-templates, VERSION file - >- - {{ 'Preserved: config.md, scores.md, learning-callouts.md' - if not (force_remove is defined and force_remove | bool) + {{ 'Preserved: scores.md, learning-callouts.md' + if not (intelligent_claude_code_uninstall_force_remove is defined and intelligent_claude_code_uninstall_force_remove | bool) else 'All files removed' }} - >- {{ 'Directory preserved (contains user files)' if (intelligent_claude_code_uninstall_claude_dir_contents.matched > 0 - and not (force_remove is defined and force_remove | bool)) + and not (intelligent_claude_code_uninstall_force_remove is defined and intelligent_claude_code_uninstall_force_remove | bool)) else 'Directory removed' }} when: intelligent_claude_code_uninstall_install_directory.stat.exists - name: Display no installation found message ansible.builtin.debug: - msg: "No installation found at {{ claude_install_path }}" + msg: "No installation found at {{ intelligent_claude_code_uninstall_install_path }}" when: not intelligent_claude_code_uninstall_install_directory.stat.exists diff --git a/ansible/roles/intelligent_claude_code_uninstall/tasks/project_cleanup.yml b/ansible/roles/intelligent_claude_code_uninstall/tasks/project_cleanup.yml index f6f33463..21245eb7 100644 --- a/ansible/roles/intelligent_claude_code_uninstall/tasks/project_cleanup.yml +++ b/ansible/roles/intelligent_claude_code_uninstall/tasks/project_cleanup.yml @@ -2,41 +2,41 @@ # Project-specific cleanup tasks - name: Check if project CLAUDE.md exists ansible.builtin.stat: - path: "{{ claude_project_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md" register: intelligent_claude_code_uninstall_project_claude_md_exists - when: claude_project_path != "" + when: intelligent_claude_code_uninstall_project_path != "" - name: Remove virtual team import from project CLAUDE.md ansible.builtin.lineinfile: - path: "{{ claude_project_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md" regexp: '^@~/.claude/modes/virtual-team\.md\s*$' state: absent backup: true when: - - claude_project_path != "" + - intelligent_claude_code_uninstall_project_path != "" - intelligent_claude_code_uninstall_project_claude_md_exists.stat.exists register: intelligent_claude_code_uninstall_project_claude_cleanup - name: Remove empty lines from project CLAUDE.md after import removal ansible.builtin.lineinfile: - path: "{{ claude_project_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md" regexp: '^\s*$' state: absent when: - - claude_project_path != "" + - intelligent_claude_code_uninstall_project_path != "" - intelligent_claude_code_uninstall_project_claude_md_exists.stat.exists - intelligent_claude_code_uninstall_project_claude_cleanup.changed - name: Check if project CLAUDE.md is now empty ansible.builtin.stat: - path: "{{ claude_project_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md" register: intelligent_claude_code_uninstall_project_claude_md_after_cleanup when: - - claude_project_path != "" + - intelligent_claude_code_uninstall_project_path != "" - intelligent_claude_code_uninstall_project_claude_cleanup.changed - name: Read project CLAUDE.md content to check if empty ansible.builtin.slurp: - src: "{{ claude_project_path }}/CLAUDE.md" + src: "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md" register: intelligent_claude_code_uninstall_project_claude_content when: - - claude_project_path != "" + - intelligent_claude_code_uninstall_project_path != "" - intelligent_claude_code_uninstall_project_claude_md_after_cleanup.stat.exists - name: Determine if project CLAUDE.md is empty ansible.builtin.set_fact: @@ -44,20 +44,20 @@ {{ intelligent_claude_code_uninstall_project_claude_content.content | b64decode | trim | length == 0 }} when: - - claude_project_path != "" + - intelligent_claude_code_uninstall_project_path != "" - intelligent_claude_code_uninstall_project_claude_content is defined - name: Remove empty project CLAUDE.md file ansible.builtin.file: - path: "{{ claude_project_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md" state: absent when: - - claude_project_path != "" + - intelligent_claude_code_uninstall_project_path != "" - intelligent_claude_code_uninstall_project_claude_empty | bool - name: Display project cleanup results ansible.builtin.debug: msg: - "Project cleanup completed" - - "Project path: {{ claude_project_path }}" + - "Project path: {{ intelligent_claude_code_uninstall_project_path }}" - >- {{ 'CLAUDE.md import removed' if intelligent_claude_code_uninstall_project_claude_cleanup.changed @@ -66,4 +66,4 @@ {{ 'Empty CLAUDE.md file removed' if (intelligent_claude_code_uninstall_project_claude_empty | default(false)) else 'Project CLAUDE.md preserved' }} - when: claude_project_path != "" + when: intelligent_claude_code_uninstall_project_path != "" diff --git a/ansible/roles/intelligent_claude_code_uninstall/tasks/project_removal.yml b/ansible/roles/intelligent_claude_code_uninstall/tasks/project_removal.yml index 7a976750..a2db1e16 100644 --- a/ansible/roles/intelligent_claude_code_uninstall/tasks/project_removal.yml +++ b/ansible/roles/intelligent_claude_code_uninstall/tasks/project_removal.yml @@ -3,7 +3,7 @@ - name: Check if project CLAUDE.md exists ansible.builtin.stat: - path: "{{ claude_project_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md" register: intelligent_claude_code_uninstall_project_claude_md - name: Handle project CLAUDE.md removal @@ -11,7 +11,7 @@ block: - name: Check if import line exists in project CLAUDE.md ansible.builtin.command: - cmd: grep -q "@~/.claude/modes/virtual-team.md" "{{ claude_project_path }}/CLAUDE.md" + cmd: grep -q "@~/.claude/modes/virtual-team.md" "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md" register: intelligent_claude_code_uninstall_project_import_present failed_when: false changed_when: false @@ -21,13 +21,13 @@ block: - name: Check if project backup exists ansible.builtin.stat: - path: "{{ claude_project_path }}/CLAUDE.md.backup" + path: "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md.backup" register: intelligent_claude_code_uninstall_project_backup_exists - name: Restore project CLAUDE.md from backup ansible.builtin.copy: - src: "{{ claude_project_path }}/CLAUDE.md.backup" - dest: "{{ claude_project_path }}/CLAUDE.md" + src: "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md.backup" + dest: "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md" remote_src: true mode: '0644' when: intelligent_claude_code_uninstall_project_backup_exists.stat.exists @@ -35,7 +35,7 @@ - name: Remove project backup file after restoration ansible.builtin.file: - path: "{{ claude_project_path }}/CLAUDE.md.backup" + path: "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md.backup" state: absent when: intelligent_claude_code_uninstall_project_backup_exists.stat.exists failed_when: false @@ -45,37 +45,37 @@ block: - name: Read project CLAUDE.md content ansible.builtin.slurp: - src: "{{ claude_project_path }}/CLAUDE.md" + src: "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md" register: intelligent_claude_code_uninstall_project_content - name: Remove import line from project ansible.builtin.lineinfile: - path: "{{ claude_project_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md" line: "@~/.claude/modes/virtual-team.md" state: absent - name: Remove virtual team header from project ansible.builtin.lineinfile: - path: "{{ claude_project_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md" line: "# Virtual Development Team" state: absent - name: Remove project configuration comment ansible.builtin.lineinfile: - path: "{{ claude_project_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md" line: "" state: absent - name: Check if project CLAUDE.md is effectively empty ansible.builtin.shell: | set -o pipefail - grep -v '^[[:space:]]*$' "{{ claude_project_path }}/CLAUDE.md" | wc -l + grep -v '^[[:space:]]*$' "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md" | wc -l register: intelligent_claude_code_uninstall_project_content_lines changed_when: false - name: Remove empty project CLAUDE.md file ansible.builtin.file: - path: "{{ claude_project_path }}/CLAUDE.md" + path: "{{ intelligent_claude_code_uninstall_project_path }}/CLAUDE.md" state: absent when: intelligent_claude_code_uninstall_project_content_lines.stdout | int == 0 @@ -99,5 +99,5 @@ - name: Report no project CLAUDE.md found ansible.builtin.debug: - msg: "No project CLAUDE.md found at {{ claude_project_path }}" + msg: "No project CLAUDE.md found at {{ intelligent_claude_code_uninstall_project_path }}" when: not intelligent_claude_code_uninstall_project_claude_md.stat.exists diff --git a/ansible/roles/mcp-integration/tasks/backup_settings.yml b/ansible/roles/mcp-integration/tasks/backup_settings.yml deleted file mode 100644 index 3887123b..00000000 --- a/ansible/roles/mcp-integration/tasks/backup_settings.yml +++ /dev/null @@ -1,78 +0,0 @@ ---- -# Create backup of existing claude.json before making changes - -- name: Set default settings path - set_fact: - settings_json_path: "{{ ansible_env.HOME }}/.claude.json" - when: settings_json_path is not defined - -- name: Check if claude.json exists - stat: - path: "{{ settings_json_path }}" - register: settings_file_stat - -- name: Create backup filename with timestamp - set_fact: - settings_backup_file: "{{ settings_json_path }}.backup.{{ ansible_date_time.epoch }}" - -- name: Create backup of existing claude.json - copy: - src: "{{ settings_json_path }}" - dest: "{{ settings_backup_file }}" - mode: "0600" - backup: no - when: settings_file_stat.stat.exists - register: backup_result - failed_when: false - -- name: Handle backup creation failure - set_fact: - mcp_integration_error: "Failed to create backup of claude.json" - when: - - settings_file_stat.stat.exists - - backup_result is defined - - backup_result.failed - -- name: Initialize empty settings if file doesn't exist - set_fact: - current_settings: {} - when: not settings_file_stat.stat.exists - -- name: Read current claude.json if exists - slurp: - src: "{{ settings_json_path }}" - register: current_settings_raw - when: settings_file_stat.stat.exists - failed_when: false - -- name: Parse existing claude.json - set_fact: - current_settings: "{{ current_settings_raw.content | b64decode | from_json }}" - when: - - settings_file_stat.stat.exists - - not current_settings_raw.failed - failed_when: false - register: settings_parse_result - -- name: Handle corrupted claude.json - block: - - name: Log corrupted settings warning - debug: - msg: "Warning: Existing claude.json is corrupted. Using backup and creating fresh settings." - - - name: Initialize empty settings for corrupted file - set_fact: - current_settings: {} - when: - - settings_file_stat.stat.exists - - settings_parse_result.failed - -- name: Ensure settings directory exists - file: - path: "{{ settings_json_path | dirname }}" - state: directory - mode: "0755" - -- name: Log backup status - debug: - msg: "Settings backup created: {{ settings_backup_file if settings_file_stat.stat.exists else 'No existing settings to backup' }}" \ No newline at end of file diff --git a/ansible/roles/mcp-integration/tasks/error_handling.yml b/ansible/roles/mcp-integration/tasks/error_handling.yml deleted file mode 100644 index eeb3b0f1..00000000 --- a/ansible/roles/mcp-integration/tasks/error_handling.yml +++ /dev/null @@ -1,66 +0,0 @@ ---- -# Handle MCP integration errors with detailed recovery options - -- name: Display error details - debug: - msg: - - "MCP Integration Error: {{ mcp_integration_error }}" - - "Timestamp: {{ ansible_date_time.iso8601 }}" - - "Settings backup: {{ settings_backup_file | default('No backup created') }}" - -- name: Check if backup exists for rollback - stat: - path: "{{ settings_backup_file }}" - register: backup_exists - when: settings_backup_file is defined - -- name: Provide rollback information - debug: - msg: - - "Rollback available: {{ 'Yes' if backup_exists.stat.exists else 'No' }}" - - "To manually rollback: cp {{ settings_backup_file }} {{ settings_json_path }}" - when: settings_backup_file is defined and backup_exists.stat.exists - -- name: Provide troubleshooting guidance - debug: - msg: - - "Troubleshooting steps:" - - "1. Check MCP configuration JSON syntax" - - "2. Verify file permissions on {{ settings_json_path | dirname }}" - - "3. Ensure required environment variables are set" - - "4. Check disk space availability" - - "5. Review backup file: {{ settings_backup_file | default('N/A') }}" - -- name: Create error log entry - copy: - content: | - MCP Integration Error Log - ========================= - Timestamp: {{ ansible_date_time.iso8601 }} - Error: {{ mcp_integration_error }} - Host: {{ ansible_hostname }} - User: {{ ansible_user_id }} - Settings Path: {{ settings_json_path }} - Backup File: {{ settings_backup_file | default('None') }} - - Configuration Details: - - MCP Config File: {{ mcp_config_file | default('Not provided') }} - - Processed Servers: {{ processed_mcp_servers | default({}) | length }} - - Current Settings Valid: {{ 'Yes' if current_settings is defined else 'No' }} - - Recovery Options: - 1. Manual rollback: cp {{ settings_backup_file }} {{ settings_json_path }} - 2. Fix configuration and re-run integration - 3. Review logs for specific error details - dest: "{{ ansible_env.HOME }}/.config/claude/mcp-integration-error.log" - mode: "0600" - failed_when: false - -- name: Final error message - fail: - msg: | - MCP integration failed: {{ mcp_integration_error }} - Error log created: ~/.config/claude/mcp-integration-error.log - {% if settings_backup_file is defined and backup_exists.stat.exists %} - Original settings can be restored with: cp {{ settings_backup_file }} {{ settings_json_path }} - {% endif %} \ No newline at end of file diff --git a/ansible/roles/mcp-integration/tasks/load_env.yml b/ansible/roles/mcp-integration/tasks/load_env.yml deleted file mode 100644 index bd7b3f50..00000000 --- a/ansible/roles/mcp-integration/tasks/load_env.yml +++ /dev/null @@ -1,76 +0,0 @@ ---- -# Load and parse .env file if provided - -- name: Initialize loaded environment variables - set_fact: - loaded_env_vars: {} - -- name: Check if ENV_FILE is provided and exists - block: - - name: Display .env file path - debug: - msg: "Loading environment variables from: {{ env_file | expanduser }}" - - - name: Check if .env file exists - stat: - path: "{{ env_file | expanduser }}" - register: env_file_stat - - - name: Fail if .env file doesn't exist - fail: - msg: "Environment file not found: {{ env_file }}" - when: not env_file_stat.stat.exists - - - name: Read .env file contents - slurp: - src: "{{ env_file | expanduser }}" - register: env_file_content - - - name: Parse .env file with shell script - shell: | - # Parse .env file and output as key=value pairs - while IFS= read -r line || [[ -n "$line" ]]; do - # Skip empty lines and comments - [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue - # Process lines with = sign - if [[ "$line" =~ ^[[:space:]]*([^=]+)=(.*)$ ]]; then - key="${BASH_REMATCH[1]// /}" - value="${BASH_REMATCH[2]}" - # Remove quotes if present - if [[ "$value" =~ ^\"(.*)\"$ ]] || [[ "$value" =~ ^\'(.*)\'$ ]]; then - value="${BASH_REMATCH[1]}" - fi - echo "${key}=${value}" - fi - done < "{{ env_file | expanduser }}" - register: parsed_env_output - changed_when: false - - - name: Convert parsed output to dictionary - set_fact: - loaded_env_vars: "{{ loaded_env_vars | combine({item.split('=')[0]: item.split('=', 1)[1]}) }}" - loop: "{{ parsed_env_output.stdout_lines }}" - when: parsed_env_output.stdout_lines is defined and item | length > 0 - - - name: Display loaded environment variables - debug: - msg: "Loaded {{ loaded_env_vars | length }} environment variables from {{ env_file }}" - - - name: Debug environment variables (keys only for security) - debug: - msg: "Environment variable keys: {{ loaded_env_vars.keys() | list }}" - when: loaded_env_vars | length > 0 - - when: env_file is defined and env_file | length > 0 - rescue: - - name: Handle .env file loading error - debug: - msg: "Warning: Failed to load .env file {{ env_file }}. Continuing without environment variables." - - - name: Reset environment variables on error - set_fact: - loaded_env_vars: {} - -- name: Log .env processing completion - debug: - msg: "Environment file processing completed. {{ loaded_env_vars | length }} variables available." \ No newline at end of file diff --git a/ansible/roles/mcp-integration/tasks/main.yml b/ansible/roles/mcp-integration/tasks/main.yml deleted file mode 100644 index c6d3110a..00000000 --- a/ansible/roles/mcp-integration/tasks/main.yml +++ /dev/null @@ -1,49 +0,0 @@ ---- -# MCP Server Integration Role - Main Tasks -# Handles MCP server configuration with comprehensive error handling and validation - -- name: Initialize skip flag - set_fact: - skip_mcp_integration: false - -- name: Validate MCP configuration JSON syntax - include_tasks: validate_config.yml - when: mcp_config_file is defined and mcp_config_file != '' - -- name: Create backup of existing settings - include_tasks: backup_settings.yml - when: not skip_mcp_integration - -- name: Load environment variables from .env file - include_tasks: load_env.yml - when: not skip_mcp_integration - -- name: Process MCP configuration - include_tasks: process_config.yml - when: not skip_mcp_integration and mcp_config_file is defined and mcp_config_file != '' - -- name: Merge MCP servers into settings - include_tasks: merge_settings.yml - when: not skip_mcp_integration - -- name: Validate final configuration - include_tasks: validate_final.yml - when: not skip_mcp_integration - -- name: Handle configuration errors - include_tasks: error_handling.yml - when: mcp_integration_error is defined - -- name: Display integration summary - debug: - msg: - - "MCP Integration completed successfully" - - "Backup created: {{ settings_backup_file | default('N/A') }}" - - "Settings updated: {{ settings_json_path | default('N/A') }}" - - "MCP servers configured: {{ mcp_servers_count | default(0) }}" - when: not skip_mcp_integration - -- name: Display skip message - debug: - msg: "MCP Integration skipped - no configuration file provided" - when: skip_mcp_integration \ No newline at end of file diff --git a/ansible/roles/mcp-integration/tasks/merge_settings.yml b/ansible/roles/mcp-integration/tasks/merge_settings.yml deleted file mode 100644 index 2ca964aa..00000000 --- a/ansible/roles/mcp-integration/tasks/merge_settings.yml +++ /dev/null @@ -1,34 +0,0 @@ ---- -# Merge processed MCP servers into existing claude.json - -- name: Initialize mcpServers in current settings if not exists - set_fact: - current_settings: "{{ current_settings | combine({'mcpServers': {}}) }}" - when: "'mcpServers' not in current_settings" - -- name: Create merged MCP servers configuration - set_fact: - merged_mcp_servers: "{{ current_settings.mcpServers | combine(processed_mcp_servers) }}" - -- name: Check for duplicate MCP servers - debug: - msg: "MCP server '{{ item }}' already exists and will be updated" - when: item in current_settings.mcpServers - loop: "{{ processed_mcp_servers.keys() | list }}" - -- name: Update settings with merged MCP servers - set_fact: - final_settings: "{{ current_settings | combine({'mcpServers': merged_mcp_servers}) }}" - -- name: Validate final settings structure - fail: - msg: "Final settings structure is invalid" - when: "'mcpServers' not in final_settings" - -- name: Log merge results - debug: - msg: - - "Merged MCP configuration successfully" - - "Total MCP servers: {{ merged_mcp_servers | length }}" - - "New servers added: {{ (processed_mcp_servers.keys() | list) | difference(current_settings.mcpServers.keys() | list) | length }}" - - "Existing servers updated: {{ (processed_mcp_servers.keys() | list) | intersect(current_settings.mcpServers.keys() | list) | length }}" \ No newline at end of file diff --git a/ansible/roles/mcp-integration/tasks/process_config.yml b/ansible/roles/mcp-integration/tasks/process_config.yml deleted file mode 100644 index 868fd031..00000000 --- a/ansible/roles/mcp-integration/tasks/process_config.yml +++ /dev/null @@ -1,21 +0,0 @@ ---- -# Process MCP configuration with environment variable resolution - -- name: Initialize processed MCP servers - set_fact: - processed_mcp_servers: {} - -- name: Process each MCP server configuration - include_tasks: process_single_mcp.yml - loop: "{{ mcp_config_data.mcpServers | dict2items }}" - loop_control: - loop_var: mcp_server - -- name: Validate processed configuration - fail: - msg: "No MCP servers were processed successfully" - when: processed_mcp_servers | length == 0 - -- name: Log processing results - debug: - msg: "Successfully processed {{ processed_mcp_servers | length }} MCP servers" \ No newline at end of file diff --git a/ansible/roles/mcp-integration/tasks/process_single_mcp.yml b/ansible/roles/mcp-integration/tasks/process_single_mcp.yml deleted file mode 100644 index 1c07e57b..00000000 --- a/ansible/roles/mcp-integration/tasks/process_single_mcp.yml +++ /dev/null @@ -1,85 +0,0 @@ ---- -# Process a single MCP server configuration with environment variable resolution - -- name: Set current MCP server details - set_fact: - mcp_name: "{{ mcp_server.key }}" - mcp_config: "{{ mcp_server.value }}" - -- name: Validate MCP server name - fail: - msg: "MCP server name cannot be empty" - when: mcp_name | length == 0 - -- name: Initialize processed MCP config - set_fact: - processed_mcp_config: - command: "{{ mcp_config.command }}" - -- name: Process command arguments with environment variable resolution - block: - - name: Resolve environment variables in command arguments - set_fact: - processed_args: [] - - - name: Process each argument for environment variable resolution - set_fact: - processed_args: "{{ processed_args + [resolved_arg] }}" - vars: - var_name_match: "{{ item | regex_search('\\$\\{([^}]+)\\}', '\\1') }}" - var_name: "{{ var_name_match[0] if var_name_match else '' }}" - resolved_arg: "{{ item | regex_replace('\\$\\{' + var_name + '\\}', loaded_env_vars[var_name]) if (var_name_match and var_name in loaded_env_vars) else (item | regex_replace('\\$\\{' + var_name + '\\}', lookup('env', var_name)) if (var_name_match and lookup('env', var_name)) else item) }}" - loop: "{{ mcp_config.args | default([]) }}" - - - name: Debug variable resolution - debug: - var: loaded_env_vars - when: loaded_env_vars | length > 0 - - - name: Add processed arguments to config - set_fact: - processed_mcp_config: "{{ processed_mcp_config | combine({'args': processed_args}) }}" - when: mcp_config.args is defined and mcp_config.args | length > 0 - -- name: Process environment variables if defined - block: - - name: Initialize processed environment - set_fact: - processed_env: {} - - - name: Resolve environment variables in env section - set_fact: - processed_env: "{{ processed_env | combine({item.key: resolved_value}) }}" - vars: - var_name_match: "{{ item.value | regex_search('\\$\\{([^}]+)\\}', '\\1') }}" - var_name: "{{ var_name_match[0] if var_name_match else '' }}" - resolved_value: "{{ item.value | regex_replace('\\$\\{' + var_name + '\\}', loaded_env_vars[var_name]) if (var_name_match and var_name in loaded_env_vars) else (item.value | regex_replace('\\$\\{' + var_name + '\\}', lookup('env', var_name)) if (var_name_match and lookup('env', var_name)) else item.value) }}" - loop: "{{ mcp_config.env | dict2items }}" - - - name: Add processed environment to config - set_fact: - processed_mcp_config: "{{ processed_mcp_config | combine({'env': processed_env}) }}" - when: mcp_config.env is defined - -- name: Validate processed configuration - fail: - msg: "MCP server '{{ mcp_name }}' has empty command after processing" - when: processed_mcp_config.command | length == 0 - -- name: Add processed MCP server to collection - set_fact: - processed_mcp_servers: "{{ processed_mcp_servers | combine({mcp_name: processed_mcp_config}) }}" - -- name: Log successful processing - debug: - msg: "Successfully processed MCP server: {{ mcp_name }}" - -- name: Debug processed arguments (for testing) - debug: - msg: "Processed arguments: {{ processed_mcp_config.args | default([]) }}" - when: processed_mcp_config.args is defined - -- name: Debug processed environment variables (for testing) - debug: - msg: "Processed env vars: {{ processed_mcp_config.env | default({}) }}" - when: processed_mcp_config.env is defined \ No newline at end of file diff --git a/ansible/roles/mcp-integration/tasks/validate_config.yml b/ansible/roles/mcp-integration/tasks/validate_config.yml deleted file mode 100644 index 804e15da..00000000 --- a/ansible/roles/mcp-integration/tasks/validate_config.yml +++ /dev/null @@ -1,63 +0,0 @@ ---- -# Validate MCP configuration JSON syntax and structure - -- name: Check if MCP config file exists - stat: - path: "{{ mcp_config_file }}" - register: config_file_stat - failed_when: false - -- name: Set flag to skip MCP integration if config not found - set_fact: - skip_mcp_integration: true - when: not config_file_stat.stat.exists - -- name: Log MCP integration skip - debug: - msg: "MCP configuration file not provided or not found. Skipping MCP integration." - when: not config_file_stat.stat.exists - -- name: Read MCP configuration file - slurp: - src: "{{ mcp_config_file }}" - register: mcp_config_raw - failed_when: false - when: config_file_stat.stat.exists - -- name: Handle file read errors - fail: - msg: "Failed to read MCP configuration file: {{ mcp_config_file }}. Check file permissions." - when: config_file_stat.stat.exists and mcp_config_raw.failed - -- name: Decode and validate JSON syntax - set_fact: - mcp_config_data: "{{ mcp_config_raw.content | b64decode | from_json }}" - failed_when: false - register: json_parse_result - when: config_file_stat.stat.exists - -- name: Handle JSON syntax errors - fail: - msg: "Invalid JSON syntax in MCP configuration file: {{ mcp_config_file }}. Please check JSON formatting." - when: config_file_stat.stat.exists and json_parse_result.failed - -- name: Validate required JSON structure - fail: - msg: "MCP configuration must contain 'mcpServers' object" - when: config_file_stat.stat.exists and 'mcpServers' not in mcp_config_data - -- name: Validate MCP servers structure - fail: - msg: "MCP server '{{ item.key }}' missing required 'command' field" - when: config_file_stat.stat.exists and 'command' not in item.value - loop: "{{ mcp_config_data.mcpServers | dict2items | default([]) }}" - -- name: Count MCP servers for processing - set_fact: - mcp_servers_count: "{{ mcp_config_data.mcpServers | length }}" - when: config_file_stat.stat.exists - -- name: Log successful validation - debug: - msg: "MCP configuration validated successfully. Found {{ mcp_servers_count }} MCP servers." - when: config_file_stat.stat.exists \ No newline at end of file diff --git a/ansible/roles/mcp-integration/tasks/validate_final.yml b/ansible/roles/mcp-integration/tasks/validate_final.yml deleted file mode 100644 index 090cb095..00000000 --- a/ansible/roles/mcp-integration/tasks/validate_final.yml +++ /dev/null @@ -1,74 +0,0 @@ ---- -# Validate final merged configuration before writing - -- name: Validate final settings JSON structure - fail: - msg: "Final settings must be a valid JSON object" - when: final_settings is not mapping - -- name: Validate mcpServers structure - fail: - msg: "mcpServers must be a valid JSON object" - when: final_settings.mcpServers is not mapping - -- name: Validate each MCP server configuration - include_tasks: validate_single_mcp.yml - loop: "{{ final_settings.mcpServers | dict2items }}" - loop_control: - loop_var: mcp_server_item - -- name: Test JSON serialization - set_fact: - settings_json_test: "{{ final_settings | to_nice_json }}" - failed_when: false - register: json_test_result - -- name: Handle JSON serialization failure - fail: - msg: "Final settings cannot be serialized to valid JSON" - when: json_test_result.failed - -- name: Write final settings to file - copy: - content: "{{ final_settings | to_nice_json }}" - dest: "{{ settings_json_path }}" - mode: "0600" - backup: no - register: write_result - failed_when: false - -- name: Handle write failure with rollback - block: - - name: Log write failure - debug: - msg: "Failed to write claude.json, attempting rollback" - - - name: Rollback to backup if write failed - copy: - src: "{{ settings_backup_file }}" - dest: "{{ settings_json_path }}" - mode: "0600" - when: settings_backup_file is defined - - - name: Set rollback error - set_fact: - mcp_integration_error: "Failed to write claude.json and rollback completed" - - - name: Fail with rollback message - fail: - msg: "Settings write failed. Original settings have been restored from backup." - when: write_result.failed - -- name: Verify written file - stat: - path: "{{ settings_json_path }}" - register: written_file_stat - -- name: Validate written file size - fail: - msg: "Written claude.json file is empty or corrupted" - when: written_file_stat.stat.size == 0 - -- name: Log successful validation - debug: - msg: "Final configuration validated and written successfully" \ No newline at end of file diff --git a/ansible/roles/mcp-integration/tasks/validate_single_mcp.yml b/ansible/roles/mcp-integration/tasks/validate_single_mcp.yml deleted file mode 100644 index 5913400e..00000000 --- a/ansible/roles/mcp-integration/tasks/validate_single_mcp.yml +++ /dev/null @@ -1,46 +0,0 @@ ---- -# Validate a single MCP server configuration - -- name: Set MCP details for validation - set_fact: - validate_mcp_name: "{{ mcp_server_item.key }}" - validate_mcp_config: "{{ mcp_server_item.value }}" - -- name: Validate MCP server name is not empty - fail: - msg: "MCP server name cannot be empty" - when: validate_mcp_name | length == 0 - -- name: Validate command field exists - fail: - msg: "MCP server '{{ validate_mcp_name }}' missing required 'command' field" - when: "'command' not in validate_mcp_config" - -- name: Validate command is not empty - fail: - msg: "MCP server '{{ validate_mcp_name }}' has empty command" - when: validate_mcp_config.command | length == 0 - -- name: Validate args field if present - fail: - msg: "MCP server '{{ validate_mcp_name }}' args field must be a list" - when: - - "'args' in validate_mcp_config" - - validate_mcp_config.args is not sequence - -- name: Validate env field if present - fail: - msg: "MCP server '{{ validate_mcp_name }}' env field must be an object" - when: - - "'env' in validate_mcp_config" - - validate_mcp_config.env is not mapping - -- name: Check for unresolved environment variables - debug: - msg: "Warning: MCP server '{{ validate_mcp_name }}' contains unresolved variable: {{ item }}" - when: "'${' in item" - loop: "{{ validate_mcp_config.args | default([]) }}" - -- name: Log successful MCP validation - debug: - msg: "MCP server '{{ validate_mcp_name }}' validated successfully" \ No newline at end of file diff --git a/ansible/roles/mcp_integration/tasks/backup_settings.yml b/ansible/roles/mcp_integration/tasks/backup_settings.yml new file mode 100644 index 00000000..d719b324 --- /dev/null +++ b/ansible/roles/mcp_integration/tasks/backup_settings.yml @@ -0,0 +1,82 @@ +--- +# Create backup of existing claude.json before making changes + +- name: Set default settings path + ansible.builtin.set_fact: + mcp_integration_settings_json_path: "{{ ansible_env.HOME }}/.claude.json" + when: mcp_integration_settings_json_path is not defined + +- name: Check if claude.json exists + ansible.builtin.stat: + path: "{{ mcp_integration_settings_json_path }}" + register: mcp_integration_settings_file_stat + +- name: Create backup filename with timestamp + ansible.builtin.set_fact: + mcp_integration_settings_backup_file: "{{ mcp_integration_settings_json_path }}.backup.{{ ansible_date_time.epoch }}" + +- name: Create backup of existing claude.json + ansible.builtin.copy: + src: "{{ mcp_integration_settings_json_path }}" + dest: "{{ mcp_integration_settings_backup_file }}" + mode: "0600" + backup: false + when: mcp_integration_settings_file_stat.stat.exists + register: mcp_integration_backup_result + failed_when: false + +- name: Handle backup creation failure + ansible.builtin.set_fact: + mcp_integration_error: "Failed to create backup of claude.json" + when: + - mcp_integration_settings_file_stat.stat.exists + - mcp_integration_backup_result is defined + - mcp_integration_backup_result.failed + +- name: Initialize empty settings if file doesn't exist + ansible.builtin.set_fact: + mcp_integration_current_settings: {} + when: not mcp_integration_settings_file_stat.stat.exists + +- name: Read current claude.json if exists + ansible.builtin.slurp: + src: "{{ mcp_integration_settings_json_path }}" + register: mcp_integration_current_settings_raw + when: mcp_integration_settings_file_stat.stat.exists + failed_when: false + +- name: Parse existing claude.json + ansible.builtin.set_fact: + mcp_integration_current_settings: "{{ mcp_integration_current_settings_raw.content | b64decode | from_json }}" + when: + - mcp_integration_settings_file_stat.stat.exists + - not mcp_integration_current_settings_raw.failed + failed_when: false + register: mcp_integration_settings_parse_result + +- name: Handle corrupted claude.json + when: + - mcp_integration_settings_file_stat.stat.exists + - mcp_integration_settings_parse_result.failed + block: + - name: Log corrupted settings warning + ansible.builtin.debug: + msg: "Warning: Existing claude.json is corrupted. Using backup and creating fresh settings." + + - name: Initialize empty settings for corrupted file + ansible.builtin.set_fact: + mcp_integration_current_settings: {} + +- name: Ensure settings directory exists + ansible.builtin.file: + path: "{{ mcp_integration_settings_json_path | dirname }}" + state: directory + mode: "0755" + +- name: Log backup status + ansible.builtin.debug: + msg: >- + Settings backup created: {{ + mcp_integration_settings_backup_file + if mcp_integration_settings_file_stat.stat.exists + else 'No existing settings to backup' }} diff --git a/ansible/roles/mcp_integration/tasks/error_handling.yml b/ansible/roles/mcp_integration/tasks/error_handling.yml new file mode 100644 index 00000000..4631f28b --- /dev/null +++ b/ansible/roles/mcp_integration/tasks/error_handling.yml @@ -0,0 +1,66 @@ +--- +# Handle MCP integration errors with detailed recovery options + +- name: Display error details + ansible.builtin.debug: + msg: + - "MCP Integration Error: {{ mcp_integration_error }}" + - "Timestamp: {{ ansible_date_time.iso8601 }}" + - "Settings backup: {{ mcp_integration_settings_backup_file | default('No backup created') }}" + +- name: Check if backup exists for rollback + ansible.builtin.stat: + path: "{{ mcp_integration_settings_backup_file }}" + register: mcp_integration_backup_exists + when: mcp_integration_settings_backup_file is defined + +- name: Provide rollback information + ansible.builtin.debug: + msg: + - "Rollback available: {{ 'Yes' if mcp_integration_backup_exists.stat.exists else 'No' }}" + - "To manually rollback: cp {{ mcp_integration_settings_backup_file }} {{ mcp_integration_settings_json_path }}" + when: mcp_integration_settings_backup_file is defined and mcp_integration_backup_exists.stat.exists + +- name: Provide troubleshooting guidance + ansible.builtin.debug: + msg: + - "Troubleshooting steps:" + - "1. Check MCP configuration JSON syntax" + - "2. Verify file permissions on {{ mcp_integration_settings_json_path | dirname }}" + - "3. Ensure required environment variables are set" + - "4. Check disk space availability" + - "5. Review backup file: {{ mcp_integration_settings_backup_file | default('N/A') }}" + +- name: Create error log entry + ansible.builtin.copy: + content: | + MCP Integration Error Log + ========================= + Timestamp: {{ ansible_date_time.iso8601 }} + Error: {{ mcp_integration_error }} + Host: {{ ansible_hostname }} + User: {{ ansible_user_id }} + Settings Path: {{ mcp_integration_settings_json_path }} + Backup File: {{ mcp_integration_settings_backup_file | default('None') }} + + Configuration Details: + - MCP Config File: {{ mcp_integration_config_file | default('Not provided') }} + - Processed Servers: {{ mcp_integration_processed_servers | default({}) | length }} + - Current Settings Valid: {{ 'Yes' if mcp_integration_current_settings is defined else 'No' }} + + Recovery Options: + 1. Manual rollback: cp {{ mcp_integration_settings_backup_file }} {{ mcp_integration_settings_json_path }} + 2. Fix configuration and re-run integration + 3. Review logs for specific error details + dest: "{{ ansible_env.HOME }}/.config/claude/mcp-integration-error.log" + mode: "0600" + failed_when: false + +- name: Final error message + ansible.builtin.fail: + msg: | + MCP integration failed: {{ mcp_integration_error }} + Error log created: ~/.config/claude/mcp-integration-error.log + {% if mcp_integration_settings_backup_file is defined and mcp_integration_backup_exists.stat.exists %} + Original settings can be restored with: cp {{ mcp_integration_settings_backup_file }} {{ mcp_integration_settings_json_path }} + {% endif %} diff --git a/ansible/roles/mcp_integration/tasks/load_env.yml b/ansible/roles/mcp_integration/tasks/load_env.yml new file mode 100644 index 00000000..e4f73529 --- /dev/null +++ b/ansible/roles/mcp_integration/tasks/load_env.yml @@ -0,0 +1,78 @@ +--- +# Load and parse .env file if provided + +- name: Initialize loaded environment variables + ansible.builtin.set_fact: + mcp_integration_loaded_env_vars: {} + +- name: Check if ENV_FILE is provided and exists + when: mcp_integration_env_file is defined and mcp_integration_env_file | length > 0 + block: + - name: Display .env file path + ansible.builtin.debug: + msg: "Loading environment variables from: {{ mcp_integration_env_file | expanduser }}" + + - name: Check if .env file exists + ansible.builtin.stat: + path: "{{ mcp_integration_env_file | expanduser }}" + register: mcp_integration_env_file_stat + + - name: Fail if .env file doesn't exist + ansible.builtin.fail: + msg: "Environment file not found: {{ mcp_integration_env_file }}" + when: not mcp_integration_env_file_stat.stat.exists + + - name: Read .env file contents + ansible.builtin.slurp: + src: "{{ mcp_integration_env_file | expanduser }}" + register: mcp_integration_env_file_content + + - name: Parse .env file with shell script + ansible.builtin.shell: | + # Parse .env file and output as key=value pairs + while IFS= read -r line || [[ -n "$line" ]]; do + # Skip empty lines and comments + [[ -z "$line" || "$line" =~ ^[[:space:]]*# ]] && continue + # Process lines with = sign + if [[ "$line" =~ ^[[:space:]]*([^=]+)=(.*)$ ]]; then + key="${BASH_REMATCH[1]// /}" + value="${BASH_REMATCH[2]}" + # Remove quotes if present + if [[ "$value" =~ ^\"(.*)\"$ ]] || [[ "$value" =~ ^\'(.*)\'$ ]]; then + value="${BASH_REMATCH[1]}" + fi + echo "${key}=${value}" + fi + done < "{{ mcp_integration_env_file | expanduser }}" + register: mcp_integration_parsed_env_output + changed_when: false + + - name: Convert parsed output to dictionary + ansible.builtin.set_fact: + mcp_integration_loaded_env_vars: "{{ mcp_integration_loaded_env_vars | combine({item.split('=')[0]: item.split('=', 1)[1]}) }}" + loop: "{{ mcp_integration_parsed_env_output.stdout_lines }}" + when: mcp_integration_parsed_env_output.stdout_lines is defined and item | length > 0 + + - name: Display loaded environment variables + ansible.builtin.debug: + msg: "Loaded {{ mcp_integration_loaded_env_vars | length }} environment variables from {{ mcp_integration_env_file }}" + + - name: Debug environment variables (keys only for security) + ansible.builtin.debug: + msg: "Environment variable keys: {{ mcp_integration_loaded_env_vars.keys() | list }}" + when: mcp_integration_loaded_env_vars | length > 0 + + rescue: + - name: Handle .env file loading error + ansible.builtin.debug: + msg: >- + Warning: Failed to load .env file {{ mcp_integration_env_file }}. + Continuing without environment variables. + + - name: Reset environment variables on error + ansible.builtin.set_fact: + mcp_integration_loaded_env_vars: {} + +- name: Log .env processing completion + ansible.builtin.debug: + msg: "Environment file processing completed. {{ mcp_integration_loaded_env_vars | length }} variables available." diff --git a/ansible/roles/mcp_integration/tasks/main.yml b/ansible/roles/mcp_integration/tasks/main.yml new file mode 100644 index 00000000..38908460 --- /dev/null +++ b/ansible/roles/mcp_integration/tasks/main.yml @@ -0,0 +1,49 @@ +--- +# MCP Server Integration Role - Main Tasks +# Handles MCP server configuration with comprehensive error handling and validation + +- name: Initialize skip flag + ansible.builtin.set_fact: + mcp_integration_skip: false + +- name: Validate MCP configuration JSON syntax + ansible.builtin.include_tasks: validate_config.yml + when: mcp_integration_config_file is defined and mcp_integration_config_file != '' + +- name: Create backup of existing settings + ansible.builtin.include_tasks: backup_settings.yml + when: not mcp_integration_skip + +- name: Load environment variables from .env file + ansible.builtin.include_tasks: load_env.yml + when: not mcp_integration_skip + +- name: Process MCP configuration + ansible.builtin.include_tasks: process_config.yml + when: not mcp_integration_skip and mcp_integration_config_file is defined and mcp_integration_config_file != '' + +- name: Merge MCP servers into settings + ansible.builtin.include_tasks: merge_settings.yml + when: not mcp_integration_skip + +- name: Validate final configuration + ansible.builtin.include_tasks: validate_final.yml + when: not mcp_integration_skip + +- name: Handle configuration errors + ansible.builtin.include_tasks: error_handling.yml + when: mcp_integration_error is defined + +- name: Display integration summary + ansible.builtin.debug: + msg: + - "MCP Integration completed successfully" + - "Backup created: {{ mcp_integration_settings_backup_file | default('N/A') }}" + - "Settings updated: {{ mcp_integration_settings_json_path | default('N/A') }}" + - "MCP servers configured: {{ mcp_integration_servers_count | default(0) }}" + when: not mcp_integration_skip + +- name: Display skip message + ansible.builtin.debug: + msg: "MCP Integration skipped - no configuration file provided" + when: mcp_integration_skip diff --git a/ansible/roles/mcp_integration/tasks/merge_settings.yml b/ansible/roles/mcp_integration/tasks/merge_settings.yml new file mode 100644 index 00000000..40eac38a --- /dev/null +++ b/ansible/roles/mcp_integration/tasks/merge_settings.yml @@ -0,0 +1,42 @@ +--- +# Merge processed MCP servers into existing claude.json + +- name: Initialize mcpServers in current settings if not exists + ansible.builtin.set_fact: + mcp_integration_current_settings: "{{ mcp_integration_current_settings | combine({'mcpServers': {}}) }}" + when: "'mcpServers' not in mcp_integration_current_settings" + +- name: Create merged MCP servers configuration + ansible.builtin.set_fact: + mcp_integration_merged_servers: "{{ mcp_integration_current_settings.mcpServers | combine(mcp_integration_processed_servers) }}" + +- name: Check for duplicate MCP servers + ansible.builtin.debug: + msg: "MCP server '{{ item }}' already exists and will be updated" + when: item in mcp_integration_current_settings.mcpServers + loop: "{{ mcp_integration_processed_servers.keys() | list }}" + +- name: Update settings with merged MCP servers + ansible.builtin.set_fact: + mcp_integration_final_settings: "{{ mcp_integration_current_settings | combine({'mcpServers': mcp_integration_merged_servers}) }}" + +- name: Validate final settings structure + ansible.builtin.fail: + msg: "Final settings structure is invalid" + when: "'mcpServers' not in mcp_integration_final_settings" + +- name: Log merge results + ansible.builtin.debug: + msg: + - "Merged MCP configuration successfully" + - "Total MCP servers: {{ mcp_integration_merged_servers | length }}" + - >- + New servers added: {{ + (mcp_integration_processed_servers.keys() | list) + | difference(mcp_integration_current_settings.mcpServers.keys() | list) + | length }} + - >- + Existing servers updated: {{ + (mcp_integration_processed_servers.keys() | list) + | intersect(mcp_integration_current_settings.mcpServers.keys() | list) + | length }} diff --git a/ansible/roles/mcp_integration/tasks/process_config.yml b/ansible/roles/mcp_integration/tasks/process_config.yml new file mode 100644 index 00000000..ff38d6fd --- /dev/null +++ b/ansible/roles/mcp_integration/tasks/process_config.yml @@ -0,0 +1,21 @@ +--- +# Process MCP configuration with environment variable resolution + +- name: Initialize processed MCP servers + ansible.builtin.set_fact: + mcp_integration_processed_servers: {} + +- name: Process each MCP server configuration + ansible.builtin.include_tasks: process_single_mcp.yml + loop: "{{ mcp_integration_config_data.mcpServers | dict2items }}" + loop_control: + loop_var: mcp_integration_server + +- name: Validate processed configuration + ansible.builtin.fail: + msg: "No MCP servers were processed successfully" + when: mcp_integration_processed_servers | length == 0 + +- name: Log processing results + ansible.builtin.debug: + msg: "Successfully processed {{ mcp_integration_processed_servers | length }} MCP servers" diff --git a/ansible/roles/mcp_integration/tasks/process_single_mcp.yml b/ansible/roles/mcp_integration/tasks/process_single_mcp.yml new file mode 100644 index 00000000..462bd97f --- /dev/null +++ b/ansible/roles/mcp_integration/tasks/process_single_mcp.yml @@ -0,0 +1,99 @@ +--- +# Process a single MCP server configuration with environment variable resolution + +- name: Set current MCP server details + ansible.builtin.set_fact: + mcp_integration_name: "{{ mcp_integration_server.key }}" + mcp_integration_config: "{{ mcp_integration_server.value }}" + +- name: Validate MCP server name + ansible.builtin.fail: + msg: "MCP server name cannot be empty" + when: mcp_integration_name | length == 0 + +- name: Initialize processed MCP config + ansible.builtin.set_fact: + mcp_integration_processed_config: + ansible.builtin.command: "{{ mcp_integration_config.command }}" + +- name: Process command arguments with environment variable resolution + when: mcp_integration_config.args is defined and mcp_integration_config.args | length > 0 + block: + - name: Resolve environment variables in command arguments + ansible.builtin.set_fact: + mcp_integration_processed_args: [] + + - name: Process each argument for environment variable resolution + ansible.builtin.set_fact: + mcp_integration_processed_args: "{{ mcp_integration_processed_args + [resolved_arg] }}" + vars: + var_name_match: "{{ item | regex_search('\\$\\{([^}]+)\\}', '\\1') }}" + var_name: "{{ var_name_match[0] if var_name_match else '' }}" + resolved_arg: >- + {% if var_name_match and var_name in mcp_integration_loaded_env_vars %} + {{ item | regex_replace('\\$\\{' + var_name + '\\}', mcp_integration_loaded_env_vars[var_name]) }} + {% elif var_name_match and lookup('env', var_name) %} + {{ item | regex_replace('\\$\\{' + var_name + '\\}', lookup('env', var_name)) }} + {% else %} + {{ item }} + {% endif %} + loop: "{{ mcp_integration_config.args | default([]) }}" + + - name: Debug variable resolution + ansible.builtin.debug: + var: mcp_integration_loaded_env_vars + when: mcp_integration_loaded_env_vars | length > 0 + + - name: Add processed arguments to config + ansible.builtin.set_fact: + mcp_integration_processed_config: "{{ mcp_integration_processed_config | combine({'args': mcp_integration_processed_args}) }}" + +- name: Process environment variables if defined + when: mcp_integration_config.env is defined + block: + - name: Initialize processed environment + ansible.builtin.set_fact: + mcp_integration_processed_env: {} + + - name: Resolve environment variables in env section + ansible.builtin.set_fact: + mcp_integration_processed_env: "{{ mcp_integration_processed_env | combine({item.key: resolved_value}) }}" + vars: + var_name_match: "{{ item.value | regex_search('\\$\\{([^}]+)\\}', '\\1') }}" + var_name: "{{ var_name_match[0] if var_name_match else '' }}" + resolved_value: >- + {% if var_name_match and var_name in mcp_integration_loaded_env_vars %} + {{ item.value | regex_replace('\\$\\{' + var_name + '\\}', mcp_integration_loaded_env_vars[var_name]) }} + {% elif var_name_match and lookup('env', var_name) %} + {{ item.value | regex_replace('\\$\\{' + var_name + '\\}', lookup('env', var_name)) }} + {% else %} + {{ item.value }} + {% endif %} + loop: "{{ mcp_integration_config.env | dict2items }}" + + - name: Add processed environment to config + ansible.builtin.set_fact: + mcp_integration_processed_config: "{{ mcp_integration_processed_config | combine({'env': mcp_integration_processed_env}) }}" + +- name: Validate processed configuration + ansible.builtin.fail: + msg: "MCP server '{{ mcp_integration_name }}' has empty command after processing" + when: mcp_integration_processed_config.command | length == 0 + +- name: Add processed MCP server to collection + ansible.builtin.set_fact: + mcp_integration_processed_servers: "{{ mcp_integration_processed_servers | combine({mcp_integration_name: mcp_integration_processed_config}) }}" + +- name: Log successful processing + ansible.builtin.debug: + msg: "Successfully processed MCP server: {{ mcp_integration_name }}" + +- name: Debug processed arguments (for testing) + ansible.builtin.debug: + msg: "Processed arguments: {{ mcp_integration_processed_config.args | default([]) }}" + when: mcp_integration_processed_config.args is defined + +- name: Debug processed environment variables (for testing) + ansible.builtin.debug: + msg: "Processed env vars: {{ mcp_integration_processed_config.env | default({}) }}" + when: mcp_integration_processed_config.env is defined diff --git a/ansible/roles/mcp_integration/tasks/validate_config.yml b/ansible/roles/mcp_integration/tasks/validate_config.yml new file mode 100644 index 00000000..6bab4425 --- /dev/null +++ b/ansible/roles/mcp_integration/tasks/validate_config.yml @@ -0,0 +1,63 @@ +--- +# Validate MCP configuration JSON syntax and structure + +- name: Check if MCP config file exists + ansible.builtin.stat: + path: "{{ mcp_integration_config_file }}" + register: mcp_integration_config_file_stat + failed_when: false + +- name: Set flag to skip MCP integration if config not found + ansible.builtin.set_fact: + mcp_integration_skip: true + when: not mcp_integration_config_file_stat.stat.exists + +- name: Log MCP integration skip + ansible.builtin.debug: + msg: "MCP configuration file not provided or not found. Skipping MCP integration." + when: not mcp_integration_config_file_stat.stat.exists + +- name: Read MCP configuration file + ansible.builtin.slurp: + src: "{{ mcp_integration_config_file }}" + register: mcp_integration_config_raw + failed_when: false + when: mcp_integration_config_file_stat.stat.exists + +- name: Handle file read errors + ansible.builtin.fail: + msg: "Failed to read MCP configuration file: {{ mcp_integration_config_file }}. Check file permissions." + when: mcp_integration_config_file_stat.stat.exists and mcp_integration_config_raw.failed + +- name: Decode and validate JSON syntax + ansible.builtin.set_fact: + mcp_integration_config_data: "{{ mcp_integration_config_raw.content | b64decode | from_json }}" + failed_when: false + register: mcp_integration_json_parse_result + when: mcp_integration_config_file_stat.stat.exists + +- name: Handle JSON syntax errors + ansible.builtin.fail: + msg: "Invalid JSON syntax in MCP configuration file: {{ mcp_integration_config_file }}. Please check JSON formatting." + when: mcp_integration_config_file_stat.stat.exists and mcp_integration_json_parse_result.failed + +- name: Validate required JSON structure + ansible.builtin.fail: + msg: "MCP configuration must contain 'mcpServers' object" + when: mcp_integration_config_file_stat.stat.exists and 'mcpServers' not in mcp_integration_config_data + +- name: Validate MCP servers structure + ansible.builtin.fail: + msg: "MCP server '{{ item.key }}' missing required 'command' field" + when: mcp_integration_config_file_stat.stat.exists and 'command' not in item.value + loop: "{{ mcp_integration_config_data.mcpServers | dict2items | default([]) }}" + +- name: Count MCP servers for processing + ansible.builtin.set_fact: + mcp_integration_servers_count: "{{ mcp_integration_config_data.mcpServers | length }}" + when: mcp_integration_config_file_stat.stat.exists + +- name: Log successful validation + ansible.builtin.debug: + msg: "MCP configuration validated successfully. Found {{ mcp_integration_servers_count }} MCP servers." + when: mcp_integration_config_file_stat.stat.exists diff --git a/ansible/roles/mcp_integration/tasks/validate_final.yml b/ansible/roles/mcp_integration/tasks/validate_final.yml new file mode 100644 index 00000000..ca693a53 --- /dev/null +++ b/ansible/roles/mcp_integration/tasks/validate_final.yml @@ -0,0 +1,74 @@ +--- +# Validate final merged configuration before writing + +- name: Validate final settings JSON structure + ansible.builtin.fail: + msg: "Final settings must be a valid JSON object" + when: mcp_integration_final_settings is not mapping + +- name: Validate mcpServers structure + ansible.builtin.fail: + msg: "mcpServers must be a valid JSON object" + when: mcp_integration_final_settings.mcpServers is not mapping + +- name: Validate each MCP server configuration + ansible.builtin.include_tasks: validate_single_mcp.yml + loop: "{{ mcp_integration_final_settings.mcpServers | dict2items }}" + loop_control: + loop_var: mcp_integration_server_item + +- name: Test JSON serialization + ansible.builtin.set_fact: + mcp_integration_settings_json_test: "{{ mcp_integration_final_settings | to_nice_json }}" + failed_when: false + register: mcp_integration_json_test_result + +- name: Handle JSON serialization failure + ansible.builtin.fail: + msg: "Final settings cannot be serialized to valid JSON" + when: mcp_integration_json_test_result.failed + +- name: Write final settings to file + ansible.builtin.copy: + content: "{{ mcp_integration_final_settings | to_nice_json }}" + dest: "{{ mcp_integration_settings_json_path }}" + mode: "0600" + backup: false + register: mcp_integration_write_result + failed_when: false + +- name: Handle write failure with rollback + when: mcp_integration_write_result.failed + block: + - name: Log write failure + ansible.builtin.debug: + msg: "Failed to write claude.json, attempting rollback" + + - name: Rollback to backup if write failed + ansible.builtin.copy: + src: "{{ mcp_integration_settings_backup_file }}" + dest: "{{ mcp_integration_settings_json_path }}" + mode: "0600" + when: mcp_integration_settings_backup_file is defined + + - name: Set rollback error + ansible.builtin.set_fact: + mcp_integration_error: "Failed to write claude.json and rollback completed" + + - name: Fail with rollback message + ansible.builtin.fail: + msg: "Settings write failed. Original settings have been restored from backup." + +- name: Verify written file + ansible.builtin.stat: + path: "{{ mcp_integration_settings_json_path }}" + register: mcp_integration_written_file_stat + +- name: Validate written file size + ansible.builtin.fail: + msg: "Written claude.json file is empty or corrupted" + when: mcp_integration_written_file_stat.stat.size == 0 + +- name: Log successful validation + ansible.builtin.debug: + msg: "Final configuration validated and written successfully" diff --git a/ansible/roles/mcp_integration/tasks/validate_single_mcp.yml b/ansible/roles/mcp_integration/tasks/validate_single_mcp.yml new file mode 100644 index 00000000..dc26b5e3 --- /dev/null +++ b/ansible/roles/mcp_integration/tasks/validate_single_mcp.yml @@ -0,0 +1,46 @@ +--- +# Validate a single MCP server configuration + +- name: Set MCP details for validation + ansible.builtin.set_fact: + mcp_integration_validate_name: "{{ mcp_integration_server_item.key }}" + mcp_integration_validate_config: "{{ mcp_integration_server_item.value }}" + +- name: Validate MCP server name is not empty + ansible.builtin.fail: + msg: "MCP server name cannot be empty" + when: mcp_integration_validate_name | length == 0 + +- name: Validate command field exists + ansible.builtin.fail: + msg: "MCP server '{{ mcp_integration_validate_name }}' missing required 'command' field" + when: "'command' not in mcp_integration_validate_config" + +- name: Validate command is not empty + ansible.builtin.fail: + msg: "MCP server '{{ mcp_integration_validate_name }}' has empty command" + when: mcp_integration_validate_config.command | length == 0 + +- name: Validate args field if present + ansible.builtin.fail: + msg: "MCP server '{{ mcp_integration_validate_name }}' args field must be a list" + when: + - "'args' in mcp_integration_validate_config" + - mcp_integration_validate_config.args is not sequence + +- name: Validate env field if present + ansible.builtin.fail: + msg: "MCP server '{{ mcp_integration_validate_name }}' env field must be an object" + when: + - "'env' in mcp_integration_validate_config" + - mcp_integration_validate_config.env is not mapping + +- name: Check for unresolved environment variables + ansible.builtin.debug: + msg: "Warning: MCP server '{{ mcp_integration_validate_name }}' contains unresolved variable: {{ item }}" + when: "'${' in item" + loop: "{{ mcp_integration_validate_config.args | default([]) }}" + +- name: Log successful MCP validation + ansible.builtin.debug: + msg: "MCP server '{{ mcp_integration_validate_name }}' validated successfully" diff --git a/ansible/uninstall.yml b/ansible/uninstall.yml index b9d5d75b..3e20b060 100644 --- a/ansible/uninstall.yml +++ b/ansible/uninstall.yml @@ -5,25 +5,26 @@ - name: Uninstall Intelligent Claude Code hosts: all - gather_facts: yes + gather_facts: true vars: target_path: "{{ target_path | default('') }}" - + tasks: - name: Determine uninstall scope and path - set_fact: - target_scope: "{{ 'project' if target_path else 'user' }}" - install_path: "{{ (target_path | realpath) + '/.claude' if target_path else ansible_env.HOME + '/.claude' }}" - project_path: "{{ target_path | realpath if target_path else '' }}" - + ansible.builtin.set_fact: + intelligent_claude_code_uninstall_target_scope: "{{ 'project' if target_path else 'user' }}" + intelligent_claude_code_uninstall_install_path: "{{ (target_path | realpath) + '/.claude' if target_path else ansible_env.HOME + '/.claude' }}" + intelligent_claude_code_uninstall_project_path: "{{ target_path | realpath if target_path else '' }}" + - name: Display uninstall target - debug: - msg: "Uninstalling from: {{ install_path }}" - + ansible.builtin.debug: + msg: "Uninstalling from: {{ intelligent_claude_code_uninstall_install_path }}" + - name: Include intelligent_claude_code uninstall role - include_role: + ansible.builtin.include_role: name: intelligent_claude_code_uninstall vars: - claude_install_path: "{{ install_path }}" - claude_project_path: "{{ project_path }}" - claude_scope: "{{ target_scope }}" \ No newline at end of file + intelligent_claude_code_uninstall_install_path: "{{ intelligent_claude_code_uninstall_install_path }}" + intelligent_claude_code_uninstall_project_path: "{{ intelligent_claude_code_uninstall_project_path }}" + intelligent_claude_code_uninstall_scope: "{{ intelligent_claude_code_uninstall_target_scope }}" + intelligent_claude_code_uninstall_force_remove: "{{ force | default(false) }}" diff --git a/best-practices-examples/README.md b/best-practices-examples/README.md deleted file mode 100644 index 6b081219..00000000 --- a/best-practices-examples/README.md +++ /dev/null @@ -1,98 +0,0 @@ -# Best Practices System - -**Dynamic injection system for methodological approaches into AgentTask generation** - -## Overview - -The best-practices system automatically discovers and injects methodological approaches and practices into AgentTasks during generation. This system follows the same auto-discovery pattern as the memory system but focuses on process and practice guidance. - -## Directory Structure - -``` -best-practices/ -├── development/ # Coding practices (TDD, Clean Code, SOLID) -├── architecture/ # Design patterns and architectural principles -├── operations/ # DevOps, GitOps, Infrastructure practices -├── security/ # DevSecOps, security practices -├── quality/ # Quality assurance methodologies -└── collaboration/ # Team practices and coordination -``` - -## Auto-Discovery Process - -During AgentTask generation, the system: - -1. **Scans best-practices/** directory for relevant practice files -2. **Matches practices** to work type and complexity -3. **Injects top 2-3 practices** into AgentTask context (max 800 tokens) -4. **Replaces template placeholders** with dynamic content - -## Practice File Format - -Create `.md` files in appropriate subdirectories: - -```markdown -# Practice Name - -**Type:** [development|architecture|operations|security|quality|collaboration] -**Applies To:** [complexity_levels, work_types] -**Keywords:** keyword1, keyword2, keyword3 - -## Description -Brief description of the practice - -## Implementation -Specific guidance for this practice - -## Quality Gates -- [ ] Checklist item 1 -- [ ] Checklist item 2 - -## Examples -Code or configuration examples -``` - -## Integration with AgentTask Generation - -The system automatically: -- **Discovers** relevant practices based on work request analysis -- **Scores** practices by relevance, recency, and project context -- **Embeds** selected practices into AgentTask complete_context -- **Replaces** template placeholders like `[CODING_STYLE]` with actual practice content - -## Supported Methodologies - -The system supports ANY methodological approach: -- **GitOps** (operations/gitops-practices.md) -- **Configuration-First** (architecture/config-first-design.md) -- **DevSecOps** (security/devsecops-integration.md) -- **Test-Driven Development** (development/tdd-practices.md) -- **Clean Architecture** (architecture/clean-architecture.md) -- **Infrastructure as Code** (operations/iac-practices.md) - -## Usage - -1. **Add practices**: Create `.md` files in appropriate subdirectories -2. **Use keywords**: Include relevant keywords for auto-discovery -3. **Specify scope**: Define what work types and complexity levels apply -4. **Let system work**: AgentTask generation automatically discovers and injects - -## Template Integration - -Replaces hardcoded placeholders: -- `[PROJECT_CODING_STYLE]` → Dynamic coding practices -- `[ARCHITECTURE_CONSTRAINTS]` → Relevant architectural practices -- `[QUALITY_STANDARDS]` → Applicable quality practices -- `[SECURITY_REQUIREMENTS]` → Security practice guidelines - -## No Manual Template Modification - -The system eliminates the need to modify AgentTask templates for customization. Simply add practice files and the auto-discovery mechanism handles injection automatically. - -## Version Control - -All best-practices are version controlled with the project, enabling: -- **Team consistency** across all AgentTask executions -- **Practice evolution** through normal git workflows -- **Project-specific** customization without system modification -- **Knowledge sharing** through documented practices \ No newline at end of file diff --git a/best-practices-examples/TEMPLATE.md b/best-practices-examples/TEMPLATE.md deleted file mode 100644 index 7255786a..00000000 --- a/best-practices-examples/TEMPLATE.md +++ /dev/null @@ -1,180 +0,0 @@ ---- -category: [CATEGORY] -tags: [TAG1, TAG2, TAG3] -created: [CREATION_DATE] -source_operation: [SOURCE_AgentTask_OR_OPERATION] -quality_score: [QUALITY_SCORE] -usage_count: 0 -effectiveness_rating: unrated -last_updated: [CREATION_DATE] ---- - -# [PRACTICE_NAME] - -## Overview -[BRIEF_DESCRIPTION_OF_PRACTICE] - -## Problem Statement -This practice addresses [SPECIFIC_CHALLENGE] that occurs when [CONTEXT_OR_SITUATION]. - -### Symptoms -- [OBSERVABLE_INDICATOR_1] -- [OBSERVABLE_INDICATOR_2] -- [COMMON_FAILURE_PATTERN] - -### Impact -Without this practice, teams typically experience [CONSEQUENCES_OF_NOT_FOLLOWING_PRACTICE]. - -## Solution Approach - -### Overview -[HIGH_LEVEL_DESCRIPTION_OF_SOLUTION_APPROACH] - -### Steps -1. **[STEP_NAME]:** [DETAILED_INSTRUCTION] - - **Validation:** [HOW_TO_VERIFY_STEP_COMPLETION] - - **If problems:** [RECOVERY_APPROACH] - - **Prerequisites:** [WHAT_MUST_BE_IN_PLACE] - -2. **[STEP_NAME]:** [DETAILED_INSTRUCTION] - - **Expected outcome:** [WHAT_SHOULD_RESULT] - - **Quality check:** [VALIDATION_CRITERIA] - -3. **[STEP_NAME]:** [DETAILED_INSTRUCTION] - - **Critical factors:** [ESSENTIAL_ELEMENTS_FOR_SUCCESS] - - **Common mistakes:** [PITFALLS_TO_AVOID] - -### Quality Gates -- [ ] [CRITICAL_VALIDATION_POINT_1] -- [ ] [CRITICAL_VALIDATION_POINT_2] -- [ ] [SUCCESS_CRITERIA_CHECKPOINT] -- [ ] [FINAL_VERIFICATION_STEP] - -## Examples - -### Scenario 1: [SPECIFIC_CONTEXT] -**Situation:** [DESCRIPTION_OF_WHEN_TO_APPLY] - -**Application:** -```bash -[SPECIFIC_COMMANDS_OR_STEPS] -``` - -**Outcome:** [EXPECTED_RESULTS] - -**Key Success Factors:** -- [CRITICAL_ELEMENT_1] -- [CRITICAL_ELEMENT_2] - -### Scenario 2: [DIFFERENT_CONTEXT] -**Situation:** [ALTERNATIVE_APPLICATION_CONTEXT] - -**Adaptation:** -[DESCRIPTION_OF_HOW_PRACTICE_ADAPTS_TO_DIFFERENT_CONTEXT] - -**Results:** [OUTCOMES_IN_THIS_CONTEXT] - -## When to Use - -### Ideal Conditions -- [CONDITION_1_FOR_OPTIMAL_APPLICATION] -- [CONDITION_2_FOR_SUCCESS] -- [ENVIRONMENTAL_REQUIREMENT] - -### Prerequisites -- [REQUIRED_TOOL_OR_KNOWLEDGE_OR_PERMISSION] -- [SYSTEM_STATE_REQUIREMENT] -- [TEAM_COORDINATION_NEED] - -### Not Recommended When -- [SITUATION_WHERE_PRACTICE_DOESNT_APPLY] -- [CONSTRAINT_THAT_PREVENTS_EFFECTIVE_USE] -- [ALTERNATIVE_APPROACH_MORE_SUITABLE] - -## Variations and Adaptations - -### For Small Teams -[HOW_TO_ADAPT_FOR_SMALLER_SCALE_OPERATIONS] - -### For Large Projects -[SCALING_CONSIDERATIONS_FOR_LARGER_OPERATIONS] - -### Tool-Specific Adaptations -- **[TOOL_NAME]:** [SPECIFIC_ADAPTATIONS_NEEDED] -- **[TOOL_NAME]:** [ALTERNATIVE_APPROACHES_WITH_DIFFERENT_TOOLS] - -## Common Pitfalls - -### Mistake: [COMMON_ERROR_1] -**Why it happens:** [ROOT_CAUSE_OF_ERROR] -**Prevention:** [HOW_TO_AVOID_THIS_ERROR] -**Recovery:** [HOW_TO_FIX_IF_ERROR_OCCURS] - -### Mistake: [COMMON_ERROR_2] -**Symptoms:** [HOW_TO_RECOGNIZE_THIS_ERROR] -**Impact:** [CONSEQUENCES_OF_THIS_ERROR] -**Solution:** [CORRECTIVE_ACTION_TO_TAKE] - -## Success Metrics - -### Quantitative Indicators -- [MEASURABLE_SUCCESS_METRIC_1] -- [MEASURABLE_SUCCESS_METRIC_2] -- [PERFORMANCE_BENCHMARK] - -### Qualitative Indicators -- [OBSERVABLE_QUALITY_IMPROVEMENT] -- [SUBJECTIVE_SUCCESS_INDICATOR] -- [TEAM_SATISFACTION_MEASURE] - -## Related Practices - -### Complementary Practices -- **[RELATED_PRACTICE_1]:** [HOW_THEY_WORK_TOGETHER] -- **[RELATED_PRACTICE_2]:** [SYNERGISTIC_BENEFITS] - -### Alternative Approaches -- **[ALTERNATIVE_1]:** [WHEN_TO_USE_INSTEAD] -- **[ALTERNATIVE_2]:** [TRADE_OFFS_TO_CONSIDER] - -## References and Resources - -### Source Operations -- [SOURCE_AgentTask_OR_OPERATION_1]: [BRIEF_DESCRIPTION_OF_SOURCE] -- [SOURCE_AgentTask_OR_OPERATION_2]: [CONTEXT_OF_SUCCESSFUL_APPLICATION] - -### External Resources -- [EXTERNAL_DOCUMENTATION_LINK]: [DESCRIPTION_OF_RESOURCE] -- [TOOL_DOCUMENTATION]: [RELEVANT_SECTIONS] - -### Learning Patterns -- [MEMORY_ENTITY_REFERENCE]: [RELATED_LEARNING_OR_PATTERN] - -## Revision History - -### [DATE] - v1.0 -- Initial creation from [SOURCE_OPERATION] -- [NOTABLE_ELEMENTS_OF_INITIAL_VERSION] - -### [DATE] - v1.1 (Template) -- [DESCRIPTION_OF_UPDATES_WHEN_PRACTICE_IS_REVISED] -- [RATIONALE_FOR_CHANGES] - -## Usage Tracking - -### Applications -- **Date:** [APPLICATION_DATE] | **Context:** [WHERE_APPLIED] | **Outcome:** [RESULTS] -- **Date:** [APPLICATION_DATE] | **Context:** [WHERE_APPLIED] | **Outcome:** [RESULTS] - -### Effectiveness Rating -**Current Rating:** [UNRATED/EXCELLENT/GOOD/NEEDS_IMPROVEMENT] -**Based on:** [NUMBER_OF_APPLICATIONS] applications -**Last Review:** [REVIEW_DATE] - -### Improvement Opportunities -- [IDENTIFIED_ENHANCEMENT_OPPORTUNITY_1] -- [IDENTIFIED_ENHANCEMENT_OPPORTUNITY_2] - ---- - -*This template provides the structure for all best practice documents generated from successful operational patterns. Each section should be completed with specific, actionable content relevant to the identified practice.* \ No newline at end of file diff --git a/best-practices-examples/architecture/configuration-first-design.md b/best-practices-examples/architecture/configuration-first-design.md deleted file mode 100644 index 9efbd7cd..00000000 --- a/best-practices-examples/architecture/configuration-first-design.md +++ /dev/null @@ -1,67 +0,0 @@ -# Configuration-First Design - -**Type:** architecture -**Applies To:** medium, large, mega -**Keywords:** configuration, design, architecture, flexibility, maintainability - -## Description - -Design approach that prioritizes external configuration over hardcoded values to enable flexible, maintainable systems. - -## Implementation - -### External Configuration -- All environment-specific values externalized -- Configuration hierarchy: runtime → file → defaults -- Validation of configuration at startup -- Hot-reload capabilities where appropriate - -### Configuration Structure -- Hierarchical configuration organization -- Environment-specific overrides -- Secure handling of sensitive values -- Configuration documentation and schemas - -### Design Principles -- Favor composition over inheritance -- Dependency injection for configurability -- Interface-based design for swappable components -- Configuration-driven behavior selection - -## Quality Gates -- [ ] No hardcoded environment-specific values -- [ ] Configuration validation implemented -- [ ] Configuration hierarchy documented -- [ ] Sensitive values properly secured -- [ ] Configuration schema defined -- [ ] Hot-reload tested where applicable - -## Examples - -### Configuration Hierarchy -```yaml -# config/defaults.yaml -database: - connection_timeout: 30 - pool_size: 10 - -# config/production.yaml -database: - host: prod-db.example.com - pool_size: 50 - -# config/development.yaml -database: - host: localhost - pool_size: 5 -``` - -### Environment Variable Override -```javascript -const config = { - database: { - host: process.env.DB_HOST || config.database.host, - port: process.env.DB_PORT || config.database.port - } -}; -``` \ No newline at end of file diff --git a/best-practices-examples/collaboration/agile-practices.md b/best-practices-examples/collaboration/agile-practices.md deleted file mode 100644 index 82551136..00000000 --- a/best-practices-examples/collaboration/agile-practices.md +++ /dev/null @@ -1,98 +0,0 @@ -# Agile Development Practices - -**Type:** collaboration -**Applies To:** medium, large, mega -**Keywords:** agile, scrum, collaboration, iterative, feedback, continuous improvement - -## Description - -Agile development practices for iterative delivery, team collaboration, and continuous improvement. - -## Implementation - -### Sprint Planning -- Break work into manageable user stories -- Estimate effort using story points or time-boxing -- Commit to realistic sprint goals -- Define clear acceptance criteria for each story - -### Daily Standups -- Share progress, blockers, and next steps -- Keep meetings focused and time-boxed (15 minutes) -- Identify impediments and address them quickly -- Foster team communication and coordination - -### Retrospectives -- Regular reflection on team processes and practices -- Identify what's working well and what needs improvement -- Create action items for continuous improvement -- Celebrate successes and learn from failures - -### Continuous Delivery -- Integrate code frequently to avoid merge conflicts -- Automate testing and deployment pipelines -- Deliver working software in short iterations -- Gather feedback early and often - -## Quality Gates -- [ ] User stories have clear acceptance criteria -- [ ] Sprint goals are realistic and achievable -- [ ] Daily standups occur and are productive -- [ ] Retrospectives held regularly with action items -- [ ] Code integrated frequently (multiple times per day) -- [ ] Automated testing pipeline in place -- [ ] Working software delivered each iteration -- [ ] Customer feedback incorporated regularly - -## Examples - -### User Story Template -``` -As a [user type] -I want [functionality] -So that [benefit/value] - -Acceptance Criteria: -- [ ] Criterion 1 -- [ ] Criterion 2 -- [ ] Criterion 3 - -Definition of Done: -- [ ] Code written and reviewed -- [ ] Tests written and passing -- [ ] Documentation updated -- [ ] Deployed to staging environment -``` - -### Daily Standup Format -``` -Yesterday: -- Completed user authentication feature -- Fixed bug in payment processing - -Today: -- Working on user profile management -- Will review PRs from team members - -Blockers: -- Waiting for API documentation from external team -- Need access to staging database -``` - -### Sprint Retrospective Format -``` -What went well: -- Great collaboration on complex feature -- Automated testing caught several bugs -- Customer feedback was very positive - -What could be improved: -- Communication about API changes -- Code review turnaround time -- Sprint planning estimation accuracy - -Action items: -- Implement API change notification process -- Set up review reminders in Slack -- Use story point poker for better estimates -``` \ No newline at end of file diff --git a/best-practices-examples/development/clean-code-practices.md b/best-practices-examples/development/clean-code-practices.md deleted file mode 100644 index ce975483..00000000 --- a/best-practices-examples/development/clean-code-practices.md +++ /dev/null @@ -1,52 +0,0 @@ -# Clean Code Practices - -**Type:** development -**Applies To:** tiny, medium, large, mega -**Keywords:** code quality, readability, maintainability, clean code - -## Description - -Clean code principles for readable, maintainable, and robust software development. - -## Implementation - -### Naming Conventions -- Use descriptive, searchable names -- Avoid mental mapping and abbreviations -- Use pronounceable names -- Use intention-revealing names - -### Function Design -- Functions should be small (20 lines max preferred) -- Functions should do one thing -- Use descriptive function names -- Minimize function arguments (3 max preferred) - -### Code Organization -- Organize code by feature, not by file type -- Keep related code close together -- Use consistent indentation and formatting -- Remove commented-out code - -## Quality Gates -- [ ] All functions have clear, descriptive names -- [ ] No function exceeds 30 lines -- [ ] No more than 3 parameters per function -- [ ] No commented-out code remains -- [ ] Code follows consistent formatting standards -- [ ] All variables have intention-revealing names - -## Examples - -### Good Function Naming -```javascript -function calculateMonthlyPayment(principal, interestRate, termInMonths) { - // Implementation -} -``` - -### Good Variable Naming -```javascript -const userAccount = getUserAccount(userId); -const isAccountActive = account.status === 'active'; -``` \ No newline at end of file diff --git a/best-practices-examples/development/test-driven-development.md b/best-practices-examples/development/test-driven-development.md deleted file mode 100644 index f89cb1d8..00000000 --- a/best-practices-examples/development/test-driven-development.md +++ /dev/null @@ -1,89 +0,0 @@ -# Test-Driven Development (TDD) - -**Type:** development -**Applies To:** medium, large, mega -**Keywords:** testing, tdd, red-green-refactor, unit tests, quality - -## Description - -Test-Driven Development approach using the Red-Green-Refactor cycle to drive design and ensure comprehensive test coverage. - -## Implementation - -### Red-Green-Refactor Cycle -- **Red**: Write a failing test that captures the desired functionality -- **Green**: Write the minimum code to make the test pass -- **Refactor**: Improve code structure while keeping tests passing - -### Test Structure -- Use descriptive test names that explain behavior -- Follow Arrange-Act-Assert pattern -- One assertion per test when possible -- Test edge cases and error conditions - -### Test Coverage -- Aim for 80%+ code coverage minimum -- Focus on testing behavior, not implementation -- Test public interfaces, not private methods -- Include integration tests for key workflows - -## Quality Gates -- [ ] All new code has corresponding tests written first -- [ ] Test coverage maintained above 80% -- [ ] All tests pass before code commit -- [ ] Test names clearly describe expected behavior -- [ ] Edge cases and error conditions tested -- [ ] Integration tests cover key workflows - -## Examples - -### TDD Cycle Example -```javascript -// RED: Write failing test -test('should calculate total price with tax', () => { - const cart = new ShoppingCart(); - cart.addItem({price: 100, quantity: 2}); - - const total = cart.getTotalWithTax(0.08); - - expect(total).toBe(216); // 200 + 16 tax -}); - -// GREEN: Make test pass -class ShoppingCart { - constructor() { - this.items = []; - } - - addItem(item) { - this.items.push(item); - } - - getTotalWithTax(taxRate) { - const subtotal = this.items.reduce((sum, item) => - sum + (item.price * item.quantity), 0); - return subtotal * (1 + taxRate); - } -} - -// REFACTOR: Improve structure while keeping tests green -``` - -### Test Organization -```javascript -describe('ShoppingCart', () => { - describe('getTotalWithTax', () => { - it('should return 0 for empty cart', () => { - // Test implementation - }); - - it('should calculate tax on single item', () => { - // Test implementation - }); - - it('should handle zero tax rate', () => { - // Test implementation - }); - }); -}); -``` \ No newline at end of file diff --git a/best-practices-examples/git/feature-branch-workflow.md b/best-practices-examples/git/feature-branch-workflow.md deleted file mode 100644 index 1c8ce2df..00000000 --- a/best-practices-examples/git/feature-branch-workflow.md +++ /dev/null @@ -1,218 +0,0 @@ ---- -category: git -tags: [branching, workflow, feature-development, clean-commits] -created: 2025-08-09 -source_operation: STORY-002-AgentTask-001-best-practices-generation -quality_score: 9.2 -usage_count: 1 -effectiveness_rating: excellent -last_updated: 2025-08-09 ---- - -# Feature Branch Workflow with Clean Integration - -## Overview -A systematic approach to feature development using dedicated branches with clean commit history and professional integration practices. - -## Problem Statement -This practice addresses the challenge of maintaining clean Git history and professional commit standards while developing complex features that require multiple commits and coordination. - -### Symptoms -- Messy commit histories with debugging commits -- Merge conflicts that break main branch stability -- Unprofessional commit messages in permanent history -- Lost work due to improper branch management - -### Impact -Without this practice, teams typically experience code review confusion, difficulty tracking changes, and unprofessional repository appearance. - -## Solution Approach - -### Overview -Create dedicated feature branches, maintain clean development practices, and integrate with professional commit standards. - -### Steps -1. **Create Feature Branch:** Create dedicated branch from main with descriptive name - - Validation: Branch created and checked out successfully - - If problems: Ensure main branch is up to date first - - Prerequisites: Clean working directory, current main branch - -2. **Develop with Clean Commits:** Make focused commits with professional messages - - Expected outcome: Each commit represents logical development unit - - Quality check: Commit messages follow professional standards - - Critical factors: No debugging commits, clear commit purposes - -3. **Maintain Professional Standards:** Apply git privacy settings and quality gates - - Validation: No AI mentions in commit messages - - Expected outcome: Professional commit history suitable for production - - Prerequisites: git_privacy=true configuration applied - -4. **Integration and Cleanup:** Clean merge or rebase into main branch - - Critical factors: No merge conflicts, clean history preserved - - Common mistakes: Merging without testing, leaving debugging commits - - Quality check: Main branch remains stable after integration - -### Quality Gates -- [ ] Feature branch created with descriptive name -- [ ] All commits have professional, descriptive messages -- [ ] No AI references in commit history (git_privacy compliance) -- [ ] Feature fully tested before integration -- [ ] Clean merge without conflicts -- [ ] Main branch stability maintained - -## Examples - -### Scenario 1: New Feature Development -**Situation:** Developing best practices generation system requiring multiple behavioral files - -**Application:** -```bash -# Create feature branch -git checkout -b feature/STORY-002-best-practices - -# Make focused commits -git add src/behaviors/best-practice-recognition.md -git commit -m "feat: Add best practice recognition behavior - -- Implement pattern detection for successful operations -- Add quality assessment criteria -- Create user interaction workflows" - -git add src/behaviors/best-practice-generation.md -git commit -m "feat: Implement best practice document generation - -- Create structured documentation generation -- Add template-based content creation -- Implement user approval workflow" - -# Clean integration -git checkout main -git pull origin main -git merge feature/STORY-002-best-practices --no-ff -git push origin main -``` - -**Outcome:** Clean commit history with professional messages, successful feature integration, no AI mentions in permanent history. - -**Key Success Factors:** -- Descriptive branch name matches work item -- Each commit represents logical development unit -- Professional commit messages with context -- Clean merge preserves development history - -### Scenario 2: Bug Fix Integration -**Situation:** Fixing critical bug with systematic approach and validation - -**Adaptation:** -Create focused branch for bug resolution, implement fix with validation, integrate with testing confirmation. - -**Results:** Bug resolved without regression, professional commit history, clear documentation of fix approach. - -## When to Use - -### Ideal Conditions -- Feature development requiring multiple commits -- Complex changes affecting multiple files -- Work requiring coordination and review -- Professional repository standards required - -### Prerequisites -- Git repository with main branch protection -- git_privacy configuration enabled -- Clear understanding of feature requirements -- Access to create and merge branches - -### Not Recommended When -- Single-line changes or typo fixes -- Emergency hotfixes requiring immediate deployment -- Working in repositories without branch protection - -## Variations and Adaptations - -### For Small Teams -- Simplified review process but maintain commit standards -- Direct merge allowed for trusted developers -- Emphasis on communication during development - -### For Large Projects -- Required pull request reviews before merge -- Automated testing gates before integration -- Detailed commit message requirements -- Squash merging for cleaner history - -### Tool-Specific Adaptations -- **GitHub:** Use pull requests with review requirements -- **GitLab:** Implement merge request workflows with approvals - -## Common Pitfalls - -### Mistake: Including Debug/Test Commits in History -**Why it happens:** Developers commit debugging code or experimental changes -**Prevention:** Use git reset or interactive rebase to clean history before merge -**Recovery:** Rebase to remove debugging commits, force push to feature branch - -### Mistake: AI References in Commit Messages -**Symptoms:** Commit messages contain "Generated with Claude Code" or AI mentions -**Impact:** Unprofessional appearance in permanent repository history -**Solution:** Apply git_privacy settings, rewrite commit messages before push - -## Success Metrics - -### Quantitative Indicators -- Zero merge conflicts during integration -- 100% compliance with commit message standards -- Clean main branch history without debugging commits - -### Qualitative Indicators -- Professional repository appearance -- Easy code review and change tracking -- Clear development progression in commit history - -## Related Practices - -### Complementary Practices -- **Code Review Standards:** Works with systematic review processes -- **Automated Testing:** Integrates with CI/CD pipelines for quality gates - -### Alternative Approaches -- **Squash and Merge:** When commit history simplification preferred -- **Rebase Workflow:** For linear history maintenance - -## References and Resources - -### Source Operations -- STORY-002-AgentTask-001: Successful multi-file feature development with clean integration -- Multiple completed AgentTasks: Consistent application of professional Git practices - -### External Resources -- Git Documentation: Branching and merging best practices -- Professional commit message standards - -### Learning Patterns -- memory/git-workflows/: Related learning patterns and successful approaches - -## Revision History - -### 2025-08-09 - v1.0 -- Initial creation from STORY-002-AgentTask-001 best practices generation -- Includes feature branch workflow, commit standards, clean integration -- Based on successful multi-file development pattern - -## Usage Tracking - -### Applications -- **Date:** 2025-08-09 | **Context:** Best practices system development | **Outcome:** Clean feature integration, professional commit history - -### Effectiveness Rating -**Current Rating:** Excellent -**Based on:** 1 application -**Last Review:** 2025-08-09 - -### Improvement Opportunities -- Add examples for different repository hosting platforms -- Include conflict resolution strategies -- Enhance integration with automated testing workflows - ---- - -*This best practice was generated from the successful implementation of the best practices generation system, demonstrating effective feature branch workflow with professional Git standards.* \ No newline at end of file diff --git a/best-practices-examples/operations/gitops-practices.md b/best-practices-examples/operations/gitops-practices.md deleted file mode 100644 index 3ad52ac5..00000000 --- a/best-practices-examples/operations/gitops-practices.md +++ /dev/null @@ -1,67 +0,0 @@ -# GitOps Practices - -**Type:** operations -**Applies To:** medium, large, mega -**Keywords:** gitops, deployment, infrastructure, automation, version control - -## Description - -GitOps methodology for infrastructure and application deployment using Git as the single source of truth. - -## Implementation - -### Git as Source of Truth -- All infrastructure and application configs in version control -- Declarative configuration management -- Environment promotion through git workflows -- Audit trail through git history - -### Automated Deployment Pipeline -- Changes trigger automated deployment workflows -- Rollback capabilities through git revert -- Environment consistency through identical configs -- No manual deployment interventions - -### Pull-Based Deployment -- Deployment agents pull changes from git -- Self-healing through continuous reconciliation -- Reduced attack surface (no push credentials) -- Environment isolation and security - -## Quality Gates -- [ ] All infrastructure defined as code in version control -- [ ] Automated deployment pipelines configured -- [ ] Environment promotion strategy defined -- [ ] Rollback procedures tested and documented -- [ ] Monitoring and alerting for deployment status -- [ ] Security scanning integrated in pipeline - -## Examples - -### GitOps Workflow Structure -```yaml -# deployment/production/app-config.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: my-app - namespace: production -spec: - replicas: 3 - selector: - matchLabels: - app: my-app - template: - metadata: - labels: - app: my-app - spec: - containers: - - name: my-app - image: my-app:v1.2.3 -``` - -### Branch Strategy -- `main` → Production environment -- `staging` → Staging environment -- `develop` → Development environment \ No newline at end of file diff --git a/best-practices-examples/quality/code-review-standards.md b/best-practices-examples/quality/code-review-standards.md deleted file mode 100644 index 5ce1d16a..00000000 --- a/best-practices-examples/quality/code-review-standards.md +++ /dev/null @@ -1,80 +0,0 @@ -# Code Review Standards - -**Type:** quality -**Applies To:** tiny, medium, large, mega -**Keywords:** code review, quality assurance, peer review, standards, collaboration - -## Description - -Comprehensive code review standards to ensure code quality, knowledge sharing, and team collaboration. - -## Implementation - -### Review Process -- All code changes require peer review before merge -- Reviews should be constructive and educational -- Review for correctness, performance, security, and maintainability -- Use automated tools to catch basic issues before human review - -### Review Checklist -- Code follows established coding standards -- Logic is clear and well-documented -- Error handling is appropriate -- Tests are included and comprehensive -- Security considerations addressed -- Performance implications considered - -### Review Communication -- Be respectful and constructive in feedback -- Explain the "why" behind suggestions -- Ask questions to understand the approach -- Acknowledge good practices and improvements - -## Quality Gates -- [ ] All changes reviewed by at least one qualified team member -- [ ] Automated checks (linting, testing) pass before review -- [ ] Security implications reviewed and addressed -- [ ] Performance impact assessed -- [ ] Documentation updated if needed -- [ ] Review feedback addressed satisfactorily -- [ ] All conversations resolved before merge - -## Examples - -### Good Review Comment -``` -Consider using a Map instead of object lookup here: - -const statusMap = new Map([ - ['pending', 'Processing'], - ['complete', 'Finished'], - ['error', 'Failed'] -]); - -This provides better performance for frequent lookups and cleaner syntax. -``` - -### Review Checklist Template -```markdown -## Code Review Checklist - -### Functionality -- [ ] Code accomplishes stated requirements -- [ ] Edge cases handled appropriately -- [ ] Error handling is robust - -### Quality -- [ ] Code is readable and well-documented -- [ ] Follows established coding standards -- [ ] No code duplication or unnecessary complexity - -### Testing -- [ ] Adequate test coverage provided -- [ ] Tests are meaningful and comprehensive -- [ ] All tests pass - -### Security -- [ ] No security vulnerabilities introduced -- [ ] Input validation where appropriate -- [ ] Sensitive data handled correctly -``` \ No newline at end of file diff --git a/best-practices-examples/security/secure-coding-practices.md b/best-practices-examples/security/secure-coding-practices.md deleted file mode 100644 index 7a2dc1eb..00000000 --- a/best-practices-examples/security/secure-coding-practices.md +++ /dev/null @@ -1,89 +0,0 @@ -# Secure Coding Practices - -**Type:** security -**Applies To:** tiny, medium, large, mega -**Keywords:** security, authentication, authorization, input validation, encryption - -## Description - -Essential security practices for developing secure applications and protecting against common vulnerabilities. - -## Implementation - -### Input Validation -- Validate all input at application boundaries -- Use whitelist validation over blacklist -- Sanitize output for different contexts (HTML, SQL, etc.) -- Implement proper error handling without information disclosure - -### Authentication & Authorization -- Use strong password policies and secure storage -- Implement proper session management -- Use principle of least privilege for authorization -- Implement multi-factor authentication for sensitive operations - -### Data Protection -- Encrypt sensitive data at rest and in transit -- Use HTTPS for all communications -- Implement proper key management -- Avoid storing sensitive data unnecessarily - -### Common Vulnerability Prevention -- Prevent SQL injection through parameterized queries -- Avoid XSS through proper output encoding -- Implement CSRF protection for state-changing operations -- Use secure headers and Content Security Policy - -## Quality Gates -- [ ] All user inputs validated and sanitized -- [ ] Authentication and authorization properly implemented -- [ ] Sensitive data encrypted at rest and in transit -- [ ] SQL injection prevention mechanisms in place -- [ ] XSS protection through output encoding -- [ ] CSRF tokens implemented for state changes -- [ ] Security headers configured (CSP, HSTS, etc.) -- [ ] Error messages don't reveal sensitive information - -## Examples - -### Input Validation -```javascript -function validateEmail(email) { - const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - if (!email || typeof email !== 'string') { - throw new ValidationError('Email is required'); - } - if (!emailRegex.test(email)) { - throw new ValidationError('Invalid email format'); - } - return email.toLowerCase().trim(); -} -``` - -### SQL Injection Prevention -```javascript -// GOOD: Parameterized query -const user = await db.query( - 'SELECT * FROM users WHERE email = ? AND active = ?', - [email, true] -); - -// BAD: String concatenation -const user = await db.query( - `SELECT * FROM users WHERE email = '${email}' AND active = true` -); -``` - -### Secure Password Hashing -```javascript -const bcrypt = require('bcrypt'); - -async function hashPassword(password) { - const saltRounds = 12; - return await bcrypt.hash(password, saltRounds); -} - -async function verifyPassword(password, hash) { - return await bcrypt.compare(password, hash); -} -``` \ No newline at end of file diff --git a/best-practices/README.md b/best-practices/README.md deleted file mode 100644 index bf2bedfa..00000000 --- a/best-practices/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Best Practices Index - -User-generated best practices for effective ICC usage. - -## Memory Storage and Retrieval -Learn when and how to store information in memory for team knowledge sharing. -[→ Details](./memory-storage-retrieval.md) - -## Git Workflow Patterns -Ensure commits comply with privacy settings and follow branch protection workflows. -[→ Details](./git-workflow-patterns.md) - -## Version Bump and GitHub Release Workflow -Complete workflow for version bumps with CHANGELOG updates, git tagging, and GitHub release creation using gh CLI. -[→ Details](./git/version-bump-and-release.md) - -## Release Workflow Automation -Configure automated release workflows with simple command interface for efficient PR-to-release pipelines. -[→ Details](./release-workflow-automation.md) - ---- - -**Note**: This directory is for user-generated best practices. Add your own by: -1. Creating a new `.md` file in this directory -2. Adding an entry to this README with headline + summary + link -3. Sharing via version control with your team diff --git a/best-practices/development/config-loading-dual-context.md b/best-practices/development/config-loading-dual-context.md deleted file mode 100644 index 210f626d..00000000 --- a/best-practices/development/config-loading-dual-context.md +++ /dev/null @@ -1,305 +0,0 @@ -# Dual-Context Configuration Loading - -## Overview -Configuration loading pattern that supports both production (installed) and development (repository) contexts without environment variables or conditional logic. - -## Problem Statement - -Hook systems and plugin architectures often need to work in two different contexts: -1. **Production/Installed Context**: Hooks installed at `~/.claude/hooks/` loading config from `~/.claude/` -2. **Development/Repository Context**: Hooks in `src/hooks/` loading config from repository root - -Using a single hardcoded path breaks one context or the other, requiring environment variables or complex detection logic. - -## Core Principle - -**FALLBACK APPROACH**: Try the production path first, then fallback to the development path if not found. - -This ensures: -- Production deployments work without modification -- Development/testing works without environment variables -- Documentation examples run as-written -- Regression tests continue functioning -- No conditional logic based on environment detection - -## Implementation Pattern - -### Basic Fallback Pattern - -```javascript -// Try production location first, then development location -let configPath = path.join(__dirname, '../..', 'config.json'); -let config = loadConfig(configPath); - -if (!config) { - // Fallback to development/repo location - configPath = path.join(__dirname, '../../..', 'config.json'); - config = loadConfig(configPath); -} - -if (!config) { - // Enhanced error reporting shows both searched paths - console.error('Config not found. Searched:'); - console.error(' - ' + path.join(__dirname, '../..', 'config.json')); - console.error(' - ' + path.join(__dirname, '../../..', 'config.json')); - - // Fallback to defaults - config = getDefaults(); -} -``` - -### Path Resolution Examples - -**Production Context** (`~/.claude/hooks/lib/config-loader.js`): -- `__dirname` = `~/.claude/hooks/lib` -- `../..` = `~/.claude/` ✅ (found) -- `../../..` = `~/` (not checked, already found) - -**Development Context** (`src/hooks/lib/config-loader.js`): -- `__dirname` = `repo/src/hooks/lib` -- `../..` = `repo/src/` ❌ (not found) -- `../../..` = `repo/` ✅ (found on fallback) - -## Real-World Example - -### Before: Single Path (Broken) - -```javascript -// Works ONLY in production, breaks in development -const configPath = path.join(__dirname, '../..', 'icc.config.default.json'); -const config = loadJsonConfig(configPath); -``` - -**Result**: -- ✅ Production: Loads from `~/.claude/icc.config.default.json` -- ❌ Development: Fails - `src/icc.config.default.json` doesn't exist -- ❌ Documentation: Examples fail -- ❌ Tests: Regression tests broken - -### After: Dual-Context Fallback (Working) - -```javascript -// Try production location first -let configPath = path.join(__dirname, '../..', 'icc.config.default.json'); -let config = loadJsonConfig(configPath); - -if (!config) { - // Fallback to development location - configPath = path.join(__dirname, '../../..', 'icc.config.default.json'); - config = loadJsonConfig(configPath); -} - -if (!config) { - console.error('[config-loader] Config not found. Searched:'); - console.error('[config-loader] - ' + path.join(__dirname, '../..', 'icc.config.default.json')); - console.error('[config-loader] - ' + path.join(__dirname, '../../..', 'icc.config.default.json')); - config = getHardcodedDefaults(); -} -``` - -**Result**: -- ✅ Production: Loads from `~/.claude/icc.config.default.json` -- ✅ Development: Loads from `repo-root/icc.config.default.json` -- ✅ Documentation: Examples work as-written -- ✅ Tests: All regression tests pass - -## Benefits - -### No Environment Variables Required -- No `NODE_ENV` checks -- No `INSTALLED_MODE` flags -- No custom environment setup -- Works out of the box in both contexts - -### Simplified Testing -- Tests run directly: `node src/hooks/agent-infrastructure-protection.js` -- No test-specific configuration -- Documentation examples copy-pasteable -- Regression tests don't need special setup - -### Production Ready -- Installed hooks work without modification -- No performance penalty (checks are fast) -- Clear error messages aid debugging -- Graceful fallback to defaults - -### Maintainability -- Single codebase for both contexts -- No conditional logic to maintain -- Clear path resolution order -- Self-documenting through comments - -## Common Use Cases - -### Hook Systems -- Production: Hooks in `~/.claude/hooks/` -- Development: Hooks in `repo/src/hooks/` -- Config in different locations relative to hook files - -### Plugin Architectures -- Production: Plugins in `~/.app/plugins/` -- Development: Plugins in `repo/src/plugins/` -- Shared config loading logic - -### CLI Tools -- Production: Installed to `/usr/local/bin/` -- Development: Run from `./src/cli/` -- Configuration in user home or repo root - -### Testing Frameworks -- Production: Installed test runners -- Development: Local test execution -- Test fixtures in different locations - -## Error Handling Best Practices - -### Enhanced Error Messages -Always show ALL searched paths when config not found: - -```javascript -if (!config) { - console.error('[loader] Configuration not found'); - console.error('[loader] Searched paths:'); - console.error('[loader] 1. ' + productionPath); - console.error('[loader] 2. ' + developmentPath); - console.error('[loader] Falling back to defaults'); - config = getDefaults(); -} -``` - -### Graceful Degradation -Provide sensible defaults as final fallback: - -```javascript -function getDefaults() { - return { - // Minimal working configuration - enabled: true, - logLevel: 'error' - }; -} -``` - -### Debug Logging -Log which path succeeded (at debug level): - -```javascript -if (config) { - if (process.env.DEBUG) { - console.debug('[loader] Config loaded from: ' + configPath); - } -} -``` - -## Anti-Patterns to Avoid - -### ❌ Environment-Based Logic -```javascript -// Don't do this -const configPath = process.env.NODE_ENV === 'production' - ? path.join(__dirname, '../..', 'config.json') - : path.join(__dirname, '../../..', 'config.json'); -``` - -**Why**: Requires environment setup, brittle, hard to test - -### ❌ Complex Detection Logic -```javascript -// Don't do this -const isInstalled = fs.existsSync(path.join(__dirname, '../..', '.installed')); -const configPath = isInstalled - ? path.join(__dirname, '../..', 'config.json') - : path.join(__dirname, '../../..', 'config.json'); -``` - -**Why**: Requires marker files, complex, error-prone - -### ❌ Silent Failures -```javascript -// Don't do this -let config = loadJsonConfig(configPath) || {}; -``` - -**Why**: No indication of failure, hard to debug, loses 140+ settings silently - -## Integration with Existing Systems - -### Works With -- ✅ npm/yarn package installations -- ✅ Ansible/Chef deployments -- ✅ Docker containers -- ✅ CI/CD pipelines -- ✅ Local development -- ✅ Documentation generation -- ✅ Test suites - -### Doesn't Require -- ❌ Environment variables -- ❌ Build-time configuration -- ❌ Conditional compilation -- ❌ Symlinks or aliases -- ❌ Path mapping -- ❌ Custom loaders - -## Quality Gates - -### Validation Checklist - -Before deploying dual-context config loading: - -- [ ] Production path points to installed location -- [ ] Development path points to repository root -- [ ] Both paths tested manually -- [ ] Error messages show both searched paths -- [ ] Graceful fallback to defaults implemented -- [ ] Debug logging available (if needed) -- [ ] Documentation updated with both contexts -- [ ] Tests cover both scenarios - -### Testing Requirements - -**Test in production context:** -```bash -$ node ~/.claude/hooks/lib/config-loader.js -✓ Config loaded successfully -``` - -**Test in development context:** -```bash -$ node src/hooks/lib/config-loader.js -✓ Config loaded successfully -``` - -**Test hook execution in production:** -```bash -$ node ~/.claude/hooks/agent-infrastructure-protection.js < test-input.json -✓ Hook runs correctly -``` - -**Test hook execution in development:** -```bash -$ node src/hooks/agent-infrastructure-protection.js < test-input.json -✓ Hook runs correctly -``` - -## Related Patterns - -- **Configuration Hierarchy**: Combines with user/project/default config layers -- **Graceful Degradation**: Provides defaults when config unavailable -- **Path Resolution**: Systematic approach to finding resources -- **Error Reporting**: Enhanced messages aid debugging - -## Success Metrics - -- Zero environment variables required -- 100% test pass rate in both contexts -- Documentation examples work without modification -- Clear error messages when config missing -- No production issues from path resolution - -## References - -- Implemented in: `src/hooks/lib/config-loader.js` -- PR: https://github.com/intelligentcode-ai/intelligent-claude-code/pull/239 -- Issue: Hook enforcement failures in other projects -- Commits: 1a38567, 490e159 diff --git a/best-practices/git-workflow-patterns.md b/best-practices/git-workflow-patterns.md deleted file mode 100644 index 0b1654a0..00000000 --- a/best-practices/git-workflow-patterns.md +++ /dev/null @@ -1,264 +0,0 @@ -# Git Privacy Compliance - -## Overview -Ensure all git commits comply with privacy settings and branch protection rules through automatic enforcement and manual verification. - -## Git Privacy Settings - -### Configuration -```json -{ - "git": { - "privacy": true, - "privacy_patterns": [ - "AI", - "Claude", - "agent", - "Generated with Claude Code", - "Co-Authored-By: Claude" - ], - "branch_protection": true, - "default_branch": "main", - "require_pr_for_main": true - } -} -``` - -### Automatic Enforcement -- **Hook**: `git-privacy-enforcement.js` enforces automatically -- **Trigger**: Before all git commit operations -- **Action**: Strips AI mentions from commit messages -- **Validation**: MANDATORY when `git.privacy: true` - -## Privacy Pattern Stripping - -### Default Patterns Removed -- "AI" references -- "Claude" mentions -- "agent" keywords -- "Generated with Claude Code" footers -- "Co-Authored-By: Claude" trailers - -### Custom Patterns -Add project-specific patterns to `git.privacy_patterns` array in `icc.config.json`. - -## Branch Protection - -### Protected Branch Rules -- **Default Branch**: Usually `main` or `master` -- **Direct Commits**: Blocked when `branch_protection: true` -- **Workflow**: Feature branch → PR → Merge -- **Override**: Emergency fixes require explicit override - -### Feature Branch Workflow -1. Create feature branch from default branch -2. Make commits on feature branch -3. Create pull request to default branch -4. Review and approve PR -5. Merge to default branch - -## Commit Message Guidelines - -### Professional Format -``` -(): - - - -