# Vincent Scaffold SDK - Cursor IDE Rules

## Project Context
This is the Vincent Scaffold SDK for creating blockchain abilities and policies that execute on Lit Actions. The framework has strict execution environment constraints and specific patterns.

## Core Constraints - CRITICAL

### Lit Actions Environment Limitations
- NEVER use `globalThis` in abilities/policies (not available)
- NEVER use `process.env` in abilities/policies (not available)  
- NEVER use Node.js built-in modules in abilities/policies
- NEVER create mock/fake data - ask for clarification instead
- State does NOT persist between executions

### laUtils API Restrictions
- laUtils can ONLY be used in Lit Actions context:
  - ✅ Ability `execute` hooks
  - ✅ Policy `evaluate` and `commit` hooks
  - ❌ NEVER in `precheck` hooks
- Import: `import { laUtils } from "@lit-protocol/vincent-scaffold-sdk/la-utils"`

## Development Patterns

### Schema-First Development
- Always define Zod schemas before implementation
- Required schemas: `abilityParamsSchema`, `precheckSuccessSchema`, `precheckFailSchema`, `executeSuccessSchema`, `executeFailSchema`
- Export types: `export type AbilityParams = z.infer<typeof abilityParamsSchema>;`

### File Structure Conventions
```
vincent-packages/
├── abilities/
│   └── ability-name/
│       ├── src/lib/
│       │   ├── schemas.ts           # Zod validation schemas
│       │   ├── vincent-ability.ts      # Main ability implementation
│       │   └── helpers/index.ts     # Ability-specific utilities
│       ├── package.json
│       └── .gitignore
└── policies/
    └── policy-name/
        ├── src/lib/
        │   ├── schemas.ts           # Zod validation schemas  
        │   ├── vincent-policy.ts    # Main policy implementation
        │   └── helpers/index.ts     # Policy-specific utilities
        ├── package.json
        └── .gitignore
```

### Ability Implementation Pattern
```typescript
import { createVincentAbility } from "@lit-protocol/vincent-ability-sdk";
import { laUtils } from "@lit-protocol/vincent-scaffold-sdk/la-utils";

export const vincentAbility = createVincentAbility({
  packageName: "{{packageName}}" as const,
  abilityDescription: "{{abilityDescription}}",
  abilityParamsSchema,
  
  precheck: async ({ abilityParams }, { succeed, fail }) => {
    // NO laUtils here - validation only
    if (!abilityParams.to.startsWith("0x")) {
      return fail({ error: "Invalid address" });
    }
    return succeed({ validated: true });
  },

  execute: async ({ abilityParams }, { succeed, fail, delegation }) => {
    // laUtils available here
    const provider = new ethers.providers.JsonRpcProvider(
  "https://yellowstone-rpc.litprotocol.com/"
);
    // Implementation...
  }
});
```

### Policy Implementation Pattern
```typescript
export const vincentPolicy = createVincentPolicy({
  packageName: "{{packageName}}" as const,
  
  precheck: async ({ abilityParams, userParams }, { allow, deny }) => {
    // NO laUtils here
  },
  
  evaluate: async ({ abilityParams, userParams }, { allow, deny }) => {
    // laUtils available here
    const result = await Lit.Actions.runOnce({ /*...*/ });
  },
  
  commit: async ({ params }, { allow, delegation }) => {
    // laUtils available here
    const provider = new ethers.providers.JsonRpcProvider(
  "https://yellowstone-rpc.litprotocol.com/"
);
  }
});
```

## Template Variables
When working with templates or creating new components:
- `{{packageName}}` - Full package name (e.g., `@company/vincent-ability-name`)
- `{{name}}` - Component name (e.g., `my-ability`)
- `{{namespace}}` - Package namespace (e.g., `@company`)
- `{{policyPackageName}}` - For abilities referencing policies
- `{{camelCaseName}}` - CamelCase version of name

## Import Patterns

### Ability/Policy Development
```typescript
import { laUtils } from "@lit-protocol/vincent-scaffold-sdk/la-utils";
import { createVincentAbility } from "@lit-protocol/vincent-ability-sdk";
import { z } from "zod";
```

### E2E Testing
```typescript
import { bundledVincentAbility } from "../../vincent-packages/abilities/my-ability/dist/index.js";
import { vincentPolicyMetadata } from "../../vincent-packages/policies/my-policy/dist/index.js";
```

## Build Script Management
When adding new abilities/policies, ALWAYS update root `package.json`:

```json
{
  "scripts": {
    "vincent:build": "dotenv -e .env -- sh -c 'cd vincent-packages/policies/my-policy && npm install && npm run build && cd ../../abilities/my-ability && npm install && npm run build'"
  }
}
```

## Common Commands
```bash
# Project initialization
npx @lit-protocol/vincent-scaffold-sdk init

# Create components
npx @lit-protocol/vincent-scaffold-sdk add ability my-ability
npx @lit-protocol/vincent-scaffold-sdk add policy my-policy

# Build and test
npm run vincent:build    # Build all components
npm run vincent:e2e      # Run E2E tests
npm run vincent:reset    # Reset test state

# Package operations (from ability/policy directory)
npx @lit-protocol/vincent-scaffold-sdk pkg build
npx @lit-protocol/vincent-scaffold-sdk pkg clean
```

## Code Style

### TypeScript
- Use strict type checking
- Define interfaces for complex objects
- Use branded types for addresses: `type EthAddress = string & { __brand: unique symbol }`
- Prefer `readonly` for immutable data
- Use template literal types where appropriate

### Error Handling
```typescript
// Structured error patterns
interface AbilityError {
  code: 'VALIDATION_ERROR' | 'EXECUTION_ERROR';
  message: string;
  details?: Record<string, unknown>;
}

// Result patterns
return succeed({ txHash, timestamp: Date.now() });
return fail({ error: "Transaction failed", code: "EXECUTION_ERROR" });
```

### Validation
```typescript
// Ethereum address validation
z.string().regex(/^0x[a-fA-F0-9]{40}$/, "Invalid Ethereum address")

// Amount validation
z.string()
  .regex(/^\d*\.?\d+$/, "Invalid amount format")
  .refine((val) => parseFloat(val) > 0, "Amount must be greater than 0")
```

## Forbidden Patterns
- Using environment variables in abilities/policies
- Creating mock/fake data
- Using laUtils in precheck hooks
- Accessing file system in abilities/policies
- Using Node.js built-ins in Lit Actions context
- Forgetting to update build scripts when adding components

## When Creating New Components
1. Use CLI commands to generate from templates
2. Update schemas first
3. Implement logic following existing patterns
4. Update build scripts in root package.json
5. Test with `npm run vincent:build && npm run vincent:e2e`

## Available laUtils APIs
```typescript
// Chain utilities
laUtils.chain.getYellowstoneProvider()
laUtils.chain.yellowstoneConfig

// Transaction handlers
laUtils.transaction.handler.contractCall()
laUtils.transaction.handler.nativeSend()

// Primitives
laUtils.transaction.primitive.getNonce()
laUtils.transaction.primitive.sendTx()
laUtils.transaction.primitive.signTx()

// Helpers
laUtils.helpers.toEthAddress()
```