npm package: @korvol/fixwright
Description: AI-powered Playwright code fixer that automatically analyzes failures and creates pull requests
Latest version: 0.1.3

# @korvol/fixwright

AI-powered Playwright code fixer that automatically analyzes failures and generates fixes using Claude.

## Features

- **AI-powered Analysis** - Uses Claude to understand failures and generate fixes
- **AgentFixer** - Autonomous agent that reads code, analyzes failures, and applies fixes
- **Failure Sources** - Read failure cases from files or databases
- **Git Integration** - Create branches and commits for fixes
- **PR Creation** - Automatically create pull requests with fixes

## Installation

```bash
npm install @korvol/fixwright
# or
pnpm add @korvol/fixwright
```

## Quick Start

### Using AgentFixer

The `AgentFixer` is an autonomous agent that analyzes failure cases and applies fixes:

```typescript
import { AgentFixer } from '@korvol/fixwright';
import { generateFailureCase } from '@korvol/stepwright';

// Create fixer with configuration
const fixer = new AgentFixer({
  model: 'claude-sonnet-4-20250514',
  maxTurns: 20,
  timeout: 300000, // 5 minutes
  verbosity: 'normal',
});

// Subscribe to events for progress feedback
fixer.on('agent:text', (text) => {
  console.log(`Agent: ${text.slice(0, 100)}...`);
});

fixer.on('agent:tool_use', (toolName, input) => {
  console.log(`Using tool: ${toolName}`);
});

// Fix a failure case
const result = await fixer.fix(failureCase, process.cwd());

if (result.success) {
  console.log('Fix applied successfully!');
  console.log(`Cause: ${result.analysis?.causeType}`);
  console.log(`Explanation: ${result.analysis?.explanation}`);
  if (result.edits) {
    console.log(`Files modified: ${result.edits.map((e) => e.filePath).join(', ')}`);
  }
} else {
  console.log(`Fix failed: ${result.error}`);
}
```

### Failure Sources

Read failure cases from different sources:

```typescript
import { FileFailureSource, DatabaseFailureSource } from '@korvol/fixwright';

// File-based source - reads from a directory
const fileSource = new FileFailureSource('./failure-cases');
const failures = await fileSource.getPending();

// Database source - reads from a database
const dbSource = new DatabaseFailureSource(databaseConnection);
const failures = await dbSource.getPending();
```

### Git Integration

Manage git branches and commits:

```typescript
import { GitManager } from '@korvol/fixwright';

const git = new GitManager({
  repoPath: process.cwd(),
  baseBranch: 'main',
});

// Create a fix branch
await git.createBranch('fix/login-selector');

// Stage and commit changes
await git.stageFiles(['src/login.ts']);
await git.commit('fix: update login selector');

// Push to remote
await git.push();
```

### PR Creation

Create pull requests with fixes:

```typescript
import { PRCreator } from '@korvol/fixwright';

const prCreator = new PRCreator({
  token: process.env.GITHUB_TOKEN,
  owner: 'my-org',
  repo: 'my-repo',
});

const prUrl = await prCreator.create({
  title: 'fix: update login selector',
  body: 'Automated fix for login page selector issue',
  head: 'fix/login-selector',
  base: 'main',
});

console.log(`PR created: ${prUrl}`);
```

## Configuration

### AgentFixer Options

```typescript
interface AgentFixerConfig {
  // Claude model to use
  model?: string; // default: 'claude-sonnet-4-20250514'

  // Maximum conversation turns
  maxTurns?: number; // default: 20

  // Timeout in milliseconds
  timeout?: number; // default: 300000 (5 min)

  // Output verbosity
  verbosity?: 'quiet' | 'normal' | 'verbose';

  // Permission mode for file operations
  permissionMode?: 'auto' | 'confirm' | 'deny';
}
```

### AgentFixer Events

```typescript
const fixer = new AgentFixer(config);

// Text output from the agent
fixer.on('agent:text', (text: string) => {});

// Tool being used
fixer.on('agent:tool_use', (toolName: string, input: unknown) => {});

// Tool result
fixer.on('agent:tool_result', (toolName: string, result: unknown) => {});

// Error occurred
fixer.on('agent:error', (error: Error) => {});
```

## FailureCase Format

Fixwright expects failure cases in this format (produced by Stepwright's `generateFailureCase`):

```typescript
interface FailureCase {
  id: string;
  status: 'pending' | 'in_progress' | 'fixed' | 'failed';
  createdAt: string;

  scriptInfo: {
    name: string;
    path: string;
    repository: string;
    baseBranch: string;
    commit: string;
  };

  failureInfo: {
    stepName: string;
    stepIndex: number;
    checkpoint?: string;
    error: {
      type: string;
      message: string;
      stack?: string;
    };
    sourceLocation?: {
      file: string;
      line: number;
      column?: number;
    };
  };

  artifacts: {
    screenshot?: string;
    dom?: string;
    console?: string;
    trace?: string;
    video?: string;
  };

  executionContext: {
    url: string;
    title?: string;
    viewport?: { width: number; height: number };
    userAgent?: string;
    timestamp: string;
  };
}
```

## AgentFixResult

```typescript
interface AgentFixResult {
  success: boolean;
  error?: string;

  // Analysis of the failure
  analysis?: {
    causeType: 'selector' | 'timing' | 'navigation' | 'logic' | 'unknown';
    explanation: string;
    confidence: number;
  };

  // Edits applied
  edits?: Array<{
    filePath: string;
    diff: string;
  }>;

  // Validation result
  validation?: {
    passed: boolean;
    output?: string;
  };
}
```

## Integration with Stepwright

```
┌─────────────────┐                    ┌─────────────────┐
│   Stepwright    │                    │    Fixwright    │
│                 │                    │                 │
│  Runs scripts   │  ── FailureCase ──▶│  Analyzes with  │
│  Captures       │                    │  Claude AI      │
│  failures       │                    │  Applies fixes  │
│                 │                    │  Creates PRs    │
└─────────────────┘                    └─────────────────┘
```

Example workflow:

```typescript
import { Stepwright, generateFailureCase } from '@korvol/stepwright';
import { AgentFixer } from '@korvol/fixwright';

// 1. Run script
const result = await script.run();

// 2. If failed, generate failure case
if (!result.success && result.failedStep) {
  const failureCase = generateFailureCase(result, {
    scriptInfo: {
      name: 'Login Script',
      path: 'scripts/login.ts',
      repository: 'my-org/my-repo',
      baseBranch: 'main',
      commit: 'abc123',
    },
    artifactPaths: {
      screenshot: result.failedStep.artifacts.screenshot,
      dom: result.failedStep.artifacts.dom,
    },
  });

  // 3. Auto-fix with Fixwright
  const fixer = new AgentFixer({
    model: 'claude-sonnet-4-20250514',
    verbosity: 'normal',
  });

  const fixResult = await fixer.fix(failureCase, process.cwd());

  if (fixResult.success) {
    console.log('Fix applied!');
  }
}
```

## Environment Variables

```bash
# Required for AI fixing
ANTHROPIC_API_KEY=your-api-key

# Required for PR creation
GITHUB_TOKEN=your-github-token
```

## License

MIT