Claude Code Plugins

Community-maintained marketplace

Feedback

validate-protection

@AEtherlight-ai/lumina
0
0

Validate protection enforcement via pre-commit hooks. Use when building or testing code protection system (PROTECT-002).

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name validate-protection
description Validate protection enforcement via pre-commit hooks. Use when building or testing code protection system (PROTECT-002).

Protection Validation Skill

What This Skill Does

Builds and tests pre-commit protection enforcement:

  • Creates scripts/validate-protection.js scanner
  • Updates .git/hooks/pre-commit with protection checks
  • Tests protection enforcement (6 scenarios)
  • Validates audit trail in git log
  • Ensures CI mode works without prompts

When Claude Should Use This

Use this skill when the user:

  • Says "build protection enforcement" or "validate protection"
  • References PROTECT-002 task
  • Wants to test pre-commit hooks
  • Mentions "protection enforcement" or "validate annotations"
  • Needs to ensure protected code is enforced

Workflow Process

1. Create Protection Validation Script

File: scripts/validate-protection.js

#!/usr/bin/env node

/**
 * Protection Validation Script
 *
 * Scans staged files for @protected/@immutable annotations and validates
 * that modifications have proper approval in commit message.
 *
 * Usage:
 *   node scripts/validate-protection.js [--ci]
 *
 * Exit codes:
 *   0 - No protected files modified, or modifications approved
 *   1 - Protected files modified without approval
 *   2 - Script error
 */

const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');

// Protection level patterns
const PROTECTION_PATTERNS = {
  immutable: /@immutable/,
  protected: /@protected/,
  maintainable: /@maintainable/
};

// Check if running in CI mode (skip interactive prompts)
const CI_MODE = process.argv.includes('--ci') || process.env.SKIP_PROTECTION_CHECK === 'true';

/**
 * Get list of staged files from git
 */
function getStagedFiles() {
  try {
    const output = execSync('git diff --cached --name-only --diff-filter=AM', {
      encoding: 'utf-8'
    });
    return output.trim().split('\n').filter(Boolean);
  } catch (error) {
    console.error('Error getting staged files:', error.message);
    return [];
  }
}

/**
 * Check if file contains protection annotations
 */
function getProtectionLevel(filePath) {
  try {
    const content = fs.readFileSync(filePath, 'utf-8');

    if (PROTECTION_PATTERNS.immutable.test(content)) {
      return 'immutable';
    }
    if (PROTECTION_PATTERNS.protected.test(content)) {
      return 'protected';
    }
    if (PROTECTION_PATTERNS.maintainable.test(content)) {
      return 'maintainable';
    }

    return null;
  } catch (error) {
    // File might be deleted or unreadable
    return null;
  }
}

/**
 * Extract protection details from file (lock date, test reference, etc.)
 */
function getProtectionDetails(filePath) {
  try {
    const content = fs.readFileSync(filePath, 'utf-8');

    // Extract lock date
    const lockDateMatch = content.match(/Locked:\s*(\d{4}-\d{2}-\d{2})/);
    const lockDate = lockDateMatch ? lockDateMatch[1] : 'Unknown';

    // Extract test reference
    const testMatch = content.match(/Test:\s*([^\n]+)/);
    const testRef = testMatch ? testMatch[1].trim() : 'Unknown';

    // Extract status
    const statusMatch = content.match(/Status:\s*([^\n]+)/);
    const status = statusMatch ? statusMatch[1].trim() : 'Unknown';

    return { lockDate, testRef, status };
  } catch (error) {
    return { lockDate: 'Unknown', testRef: 'Unknown', status: 'Unknown' };
  }
}

/**
 * Check if commit message contains approval
 */
function hasApprovalInCommitMessage() {
  // In pre-commit hook, commit message isn't available yet
  // This will be checked later by parsing git log
  // For now, we'll prompt the user interactively
  return false;
}

/**
 * Prompt user for approval (interactive mode only)
 */
function promptForApproval(protectedFiles) {
  if (CI_MODE) {
    console.error('❌ Protected files modified in CI mode without PROTECTED: commit message');
    console.error('Add "PROTECTED: [justification]" to your commit message');
    return false;
  }

  console.log('\n⚠️  WARNING: You are modifying protected files:\n');

  protectedFiles.forEach(({ file, level, details }) => {
    console.log(`  πŸ“„ ${file}`);
    console.log(`     Protection: @${level}`);
    console.log(`     Locked: ${details.lockDate}`);
    console.log(`     Test: ${details.testRef}`);
    console.log(`     Status: ${details.status}`);
    console.log('');
  });

  console.log('Protected code should not be modified without approval.');
  console.log('');
  console.log('Approval requirements:');
  console.log('  @immutable   : Architecture review + impact assessment');
  console.log('  @protected   : Technical lead approval');
  console.log('  @maintainable: Self-approval (document justification)');
  console.log('');
  console.log('Your commit message must include: PROTECTED: [justification]');
  console.log('');

  // In Node.js, we can't easily do interactive prompts in pre-commit
  // So we'll just show the warning and let the user proceed
  // They MUST add PROTECTED: to commit message
  console.log('βœ… Continue with commit (remember to add PROTECTED: to message)');
  console.log('❌ To cancel: Ctrl+C');
  console.log('');

  return true; // Allow commit, but user must add PROTECTED: message
}

/**
 * Main validation function
 */
function validateProtection() {
  console.log('πŸ” Checking for protected code modifications...\n');

  const stagedFiles = getStagedFiles();

  if (stagedFiles.length === 0) {
    console.log('βœ… No files staged for commit');
    return 0;
  }

  const protectedFiles = [];

  for (const file of stagedFiles) {
    const level = getProtectionLevel(file);

    if (level) {
      const details = getProtectionDetails(file);
      protectedFiles.push({ file, level, details });
    }
  }

  if (protectedFiles.length === 0) {
    console.log('βœ… No protected files modified');
    return 0;
  }

  // Protected files found - prompt for approval
  const approved = promptForApproval(protectedFiles);

  if (!approved) {
    console.error('\n❌ Commit blocked - protected files require approval\n');
    return 1;
  }

  console.log('⚠️  Protected files modified - ensure commit message includes PROTECTED:\n');
  return 0; // Allow commit
}

// Run validation
const exitCode = validateProtection();
process.exit(exitCode);

Make script executable:

chmod +x scripts/validate-protection.js

2. Update Pre-Commit Hook

File: .git/hooks/pre-commit

Add protection validation to existing hook (or create new):

#!/bin/sh

# Γ†therLight Pre-Commit Hook
# Validates tests, protection, and code quality before commit

# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

echo "πŸ” Running pre-commit checks..."

# 1. Run tests (existing check)
echo "\nπŸ“‹ Running tests..."
npm test
if [ $? -ne 0 ]; then
    echo "${RED}❌ Tests failed - commit blocked${NC}"
    echo "Fix failing tests or use: git commit --no-verify (NOT RECOMMENDED)"
    exit 1
fi

# 2. Check protection enforcement (NEW)
echo "\nπŸ”’ Checking protection enforcement..."
node scripts/validate-protection.js
if [ $? -ne 0 ]; then
    echo "${RED}❌ Protection validation failed - commit blocked${NC}"
    echo ""
    echo "You are modifying protected code. Required:"
    echo "  1. Get approval (see CODE_PROTECTION_POLICY.md)"
    echo "  2. Add 'PROTECTED: [justification]' to commit message"
    echo ""
    echo "To bypass (NOT RECOMMENDED): git commit --no-verify"
    exit 1
fi

# 3. Check TypeScript compilation (optional, if desired)
echo "\nπŸ”¨ Checking TypeScript compilation..."
cd vscode-lumina && npm run compile
if [ $? -ne 0 ]; then
    echo "${YELLOW}⚠️  TypeScript compilation errors (warning only)${NC}"
fi
cd ..

echo "${GREEN}βœ… All pre-commit checks passed${NC}"
exit 0

Make hook executable:

chmod +x .git/hooks/pre-commit

3. Test Protection Enforcement (6 Scenarios)

Test scenarios to validate:

Scenario 1: Modify @protected file β†’ Prompt shown

# Modify a protected file
echo "// test change" >> vscode-lumina/src/extension.ts

# Stage and attempt commit
git add vscode-lumina/src/extension.ts
git commit -m "Test change"

# Expected: Warning shown, commit allowed (must add PROTECTED:)

Scenario 2: Answer 'no' (simulated) β†’ Commit blocked

# In CI mode, protected changes should block
SKIP_PROTECTION_CHECK=false node scripts/validate-protection.js

# Expected: Exit code 1, commit blocked

Scenario 3: Answer 'yes' with PROTECTED: message β†’ Commit succeeds

git commit -m "PROTECTED: Fix critical bug in extension activation

Justification: Extension fails to activate on VS Code 1.85+
Files modified: vscode-lumina/src/extension.ts
Protection level: @protected (requires technical lead approval)
Approval: Issue #123, approved by @tech-lead

Files: 1 file changed, 5 insertions(+), 2 deletions(-)"

# Expected: Commit succeeds, git log shows PROTECTED: message

Scenario 4: Modify non-protected file β†’ No prompt

# Modify a non-protected file
echo "// test change" >> vscode-lumina/src/test/example.test.ts

git add vscode-lumina/src/test/example.test.ts
git commit -m "Add test"

# Expected: No warning, commit succeeds immediately

Scenario 5: Git log shows approval trail

# Check audit trail
git log --grep="PROTECTED:" --oneline

# Expected: Shows all protected code changes with justifications

Scenario 6: CI mode works without prompts

# Simulate CI environment
export SKIP_PROTECTION_CHECK=true

# Modify protected file
echo "// ci test" >> vscode-lumina/src/extension.ts
git add vscode-lumina/src/extension.ts
git commit -m "CI test"

# Expected: No interactive prompt, relies on commit message check

4. Validate Audit Trail

Check git log for protected changes:

# Show all protected code changes
git log --grep="PROTECTED:" --oneline

# Show changes to specific protected file
git log --grep="PROTECTED:" -- vscode-lumina/src/services/whisperClient.ts

# Show full details of protected change
git log --grep="PROTECTED:" -1 --stat

Expected audit trail format:

commit abc123def456
Author: Developer <dev@example.com>
Date:   Wed Nov 6 14:30:00 2025 -0800

    PROTECTED: Fix Whisper API timeout issue

    Justification: Whisper API response time increased to 60s
    Files modified: vscode-lumina/src/services/whisperClient.ts
    Protection level: @immutable (requires architecture approval)
    Approval: Issue #456, approved by @architect

    - Increase timeout from 30s to 60s
    - Add retry logic (3 attempts)
    - Update error messages

    Files: 1 file changed, 15 insertions(+), 5 deletions(-)

5. Document Enforcement in CODE_PROTECTION_POLICY.md

Add enforcement section:

## Enforcement Mechanisms

### Layer 1: Pre-Commit Hook
- **File:** `.git/hooks/pre-commit`
- **Trigger:** Before every git commit
- **Action:** Scans staged files for @protected/@immutable annotations
- **Result:** Warns if protected files modified, requires PROTECTED: message

### Layer 2: Static Validation
- **File:** `scripts/validate-protection.js`
- **Trigger:** Called by pre-commit hook, CI/CD pipeline
- **Action:** Validates protection annotations and approval
- **Result:** Exit code 0 (pass) or 1 (fail)

### Layer 3: Code Review
- **Trigger:** Pull request review
- **Action:** Reviewer checks for unauthorized protected changes
- **Result:** PR approval or request changes

### Layer 4: CI/CD Pipeline
- **Trigger:** Push to remote, PR creation
- **Action:** Runs validate-protection.js in CI mode
- **Result:** Build pass (green) or fail (red)

## How Enforcement Works

1. **Developer modifies code:**
   - Changes any file in workspace
   - Stages changes: `git add file.ts`

2. **Pre-commit hook runs:**
   - Scans staged files for @protected/@immutable
   - If found: Shows warning with protection details
   - Allows commit to proceed

3. **Developer writes commit message:**
   - MUST include: `PROTECTED: [justification]`
   - MUST document: Files modified, protection level, approval
   - Example: `PROTECTED: Fix critical bug (Issue #123, approved by @lead)`

4. **Commit created:**
   - Git log contains full audit trail
   - PROTECTED: prefix enables filtering
   - Justification and approval documented

5. **CI/CD validates:**
   - Runs `validate-protection.js --ci`
   - Checks commit message format
   - Blocks merge if approval missing

## CI Mode

For automated pipelines (GitHub Actions, Jenkins, etc.):

```yaml
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
  validate-protection:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Validate protection
        run: node scripts/validate-protection.js --ci

Environment variable override:

export SKIP_PROTECTION_CHECK=true  # Skip protection (CI build systems)

### 6. Performance Target

**Protection check must complete in < 200ms:**

```javascript
// Add to validate-protection.js

console.time('protection-check');

// ... validation logic ...

console.timeEnd('protection-check');
// Expected: protection-check: 45ms (well under 200ms target)

Optimization strategies:

  • Cache protection levels (don't re-scan same file)
  • Only scan staged files (not entire codebase)
  • Use regex patterns (fast string matching)
  • Exit early if no staged files

Integration with Protection Tasks

PROTECT-001 β†’ PROTECT-002 (This Skill) β†’ PROTECT-003

  1. PROTECT-001: Annotate code with @protected/@immutable
  2. PROTECT-002 (This Skill): Build enforcement (pre-commit + validation script)
  3. PROTECT-003: Complete CODE_PROTECTION_POLICY.md documentation

After PROTECT-002 completes:

  • Pre-commit hook validates protection on every commit
  • Protected changes require PROTECTED: commit message
  • Audit trail visible in git log
  • CI/CD pipelines can enforce protection

Related Files

  • scripts/validate-protection.js - Validation script (created by this skill)
  • .git/hooks/pre-commit - Pre-commit hook (updated by this skill)
  • docs/CODE_PROTECTION_POLICY.md - Protection policy (updated with enforcement)
  • internal/sprints/ACTIVE_SPRINT.toml - PROTECT-002 task definition
  • .github/workflows/ci.yml - CI/CD integration (optional)

Error Handling

Common issues and solutions:

Pre-commit hook not executing

# Check if hook is executable
ls -l .git/hooks/pre-commit
# Expected: -rwxr-xr-x (x = executable)

# Make executable if needed
chmod +x .git/hooks/pre-commit

validate-protection.js fails with "git command not found"

# Verify git is installed and in PATH
git --version

# Check Node.js is installed
node --version

Protected file not detected

# Verify annotation format
grep -n "@protected" vscode-lumina/src/extension.ts
# Expected: Should find @protected comment

# Check file is staged
git diff --cached --name-only
# Expected: Should list the file

CI mode blocking all commits

# Verify environment variable is set correctly
echo $SKIP_PROTECTION_CHECK
# Expected: true (or unset for normal mode)

# Test CI mode
SKIP_PROTECTION_CHECK=true node scripts/validate-protection.js
# Expected: Should not prompt, only check commit message

Historical Context

Why pre-commit enforcement is critical:

Without enforcement (before PROTECT-002):

  • Developers could modify @protected code freely
  • No approval process
  • No audit trail
  • Regressions slipped through code review

With enforcement (after PROTECT-002):

  • Pre-commit hook warns developers
  • PROTECTED: message documents justification
  • Git log provides audit trail
  • CI/CD blocks unauthorized changes

Pattern: Annotations mean nothing without enforcement. Pre-commit hooks make protection real.

Tips

Start simple:

  1. Create validate-protection.js first
  2. Test manually: node scripts/validate-protection.js
  3. Add to pre-commit hook
  4. Test 6 scenarios
  5. Document in CODE_PROTECTION_POLICY.md

Test thoroughly:

  • Test with @immutable file (highest protection)
  • Test with @protected file (mid-level)
  • Test with @maintainable file (lowest protection)
  • Test with non-protected file (no warning)
  • Test CI mode (no prompts)
  • Test git log audit trail

Iterate on prompt wording:

  • Make warnings clear but not scary
  • Explain approval requirements
  • Provide commit message example
  • Show protection details (lock date, test ref)

Performance matters:

  • Keep validation script fast (<200ms)
  • Only scan staged files
  • Cache protection levels if needed
  • Exit early when possible