ISSUE: No oac clean command to remove installed files
SEVERITY: Important
FILE(S): packages/cli/src/commands/clean.ts (new file), packages/cli/src/index.ts

CURRENT STATE:
packages/cli/src/index.ts imports and registers these commands (lines 25-41):
  import('./commands/init.js')
  import('./commands/update.js')
  import('./commands/add.js')
  import('./commands/apply.js')
  import('./commands/doctor.js')
  import('./commands/list.js')
  import('./commands/status.js')

There is no `clean` command. When a user uninstalls the npm package
(`npm uninstall -g @nextsystems/oac`), the `.opencode/` and `.oac/` directories
remain in every project where they ran `oac init`. There is no supported way to
remove them.

ROOT CAUSE:
The clean/uninstall lifecycle was not implemented. This is a common oversight
in CLI tools that install files into user projects.

FIX:

--- New file: packages/cli/src/commands/clean.ts ---

Follow the exact same Commander registration pattern as init.ts:
  - Export a `CleanOptions` type
  - Export a `cleanCommand(options)` async function
  - Export a `registerCleanCommand(program)` function

Full implementation plan:

```typescript
import { type Command } from 'commander'
import { existsSync } from 'node:fs'
import { rm } from 'node:fs/promises'
import { join } from 'node:path'
import { readManifest } from '../lib/manifest.js'
import { log, info, warn, error, success } from '../ui/logger.js'

export type CleanOptions = {
  force: boolean
  dryRun: boolean
  /** Remove IDE-specific files generated by oac apply (e.g. CLAUDE.md) */
  ide: boolean
}

/**
 * Implements `oac clean`:
 *  1. Reads the manifest to know which files OAC installed
 *  2. Prompts for confirmation (unless --force)
 *  3. Removes each file listed in the manifest
 *  4. Removes .oac/ directory (manifest + config)
 *  5. Removes .opencode/ directory
 *  6. Optionally removes IDE output files (--ide flag)
 */
export async function cleanCommand(options: CleanOptions): Promise<void> {
  const projectRoot = process.cwd()

  // Read manifest to know what OAC installed
  const manifest = await readManifest(projectRoot).catch(() => null)
  const trackedFiles = manifest ? Object.keys(manifest.files) : []

  // Directories always removed
  const dirsToRemove = [
    join(projectRoot, '.opencode'),
    join(projectRoot, '.oac'),
  ]

  // IDE files (only with --ide flag)
  const ideFiles = options.ide
    ? ['CLAUDE.md', 'AGENTS.md', 'GEMINI.md', 'CURSOR.md', '.cursorrules']
        .map((f) => join(projectRoot, f))
        .filter((f) => existsSync(f))
    : []

  // Print plan
  log('')
  info(options.dryRun ? '[dry-run] oac clean — no files will be removed' : 'oac clean')
  log('')
  info(`Will remove: .opencode/, .oac/ (${trackedFiles.length} tracked files)`)
  if (ideFiles.length > 0) {
    info(`IDE files:   ${ideFiles.map((f) => f.replace(projectRoot + '/', '')).join(', ')}`)
  }
  log('')

  // Confirmation prompt (unless --force or --dry-run)
  if (!options.force && !options.dryRun) {
    // Use Bun's built-in prompt (synchronous)
    const answer = prompt('Remove all OAC files from this project? [y/N] ')
    if (answer?.toLowerCase() !== 'y') {
      info('Aborted.')
      process.exit(0)
    }
  }

  if (options.dryRun) {
    info('[dry-run] Would remove:')
    for (const dir of dirsToRemove) {
      if (existsSync(dir)) info(`  ${dir.replace(projectRoot + '/', '')}`)
    }
    for (const f of ideFiles) {
      info(`  ${f.replace(projectRoot + '/', '')}`)
    }
    info('No changes made. Remove --dry-run to apply.')
    return
  }

  // Remove directories
  let removed = 0
  for (const dir of dirsToRemove) {
    if (existsSync(dir)) {
      await rm(dir, { recursive: true, force: true })
      removed++
    }
  }

  // Remove IDE files
  for (const f of ideFiles) {
    await rm(f, { force: true })
    removed++
  }

  success(`Done! Removed ${removed} item${removed !== 1 ? 's' : ''}.`)
  log('')
}

export function registerCleanCommand(program: Command): void {
  program
    .command('clean')
    .description('Remove all OAC-installed files from the current project')
    .option('--force', 'Skip confirmation prompt', false)
    .option('--dry-run', 'Show what would be removed without making changes', false)
    .option('--ide', 'Also remove IDE output files (CLAUDE.md, AGENTS.md, etc.)', false)
    .action(async (opts: { force: boolean; dryRun: boolean; ide: boolean }) => {
      await cleanCommand({ force: opts.force, dryRun: opts.dryRun, ide: opts.ide })
    })
}
```

--- Update packages/cli/src/index.ts ---

Add `registerCleanCommand` to the parallel import block and call it.

BEFORE (index.ts lines 25-41):
  const [
    { registerInitCommand },
    { registerUpdateCommand },
    { registerAddCommand },
    { registerApplyCommand },
    { registerDoctorCommand },
    { registerListCommand },
    { registerStatusCommand },
  ] = await Promise.all([
    import('./commands/init.js'),
    import('./commands/update.js'),
    import('./commands/add.js'),
    import('./commands/apply.js'),
    import('./commands/doctor.js'),
    import('./commands/list.js'),
    import('./commands/status.js'),
  ])

  registerInitCommand(program)
  registerUpdateCommand(program)
  registerAddCommand(program)
  registerApplyCommand(program)
  registerDoctorCommand(program)
  registerListCommand(program)
  registerStatusCommand(program)

AFTER:
  const [
    { registerInitCommand },
    { registerUpdateCommand },
    { registerAddCommand },
    { registerApplyCommand },
    { registerDoctorCommand },
    { registerListCommand },
    { registerStatusCommand },
    { registerCleanCommand },
  ] = await Promise.all([
    import('./commands/init.js'),
    import('./commands/update.js'),
    import('./commands/add.js'),
    import('./commands/apply.js'),
    import('./commands/doctor.js'),
    import('./commands/list.js'),
    import('./commands/status.js'),
    import('./commands/clean.js'),
  ])

  registerInitCommand(program)
  registerUpdateCommand(program)
  registerAddCommand(program)
  registerApplyCommand(program)
  registerDoctorCommand(program)
  registerListCommand(program)
  registerStatusCommand(program)
  registerCleanCommand(program)

VALIDATION:
1. Run: oac clean --dry-run (in a project with oac init already run)
   Should list .opencode/ and .oac/ without removing anything
2. Run: oac clean --force (in a test project)
   Should remove .opencode/ and .oac/ without prompting
3. Run: oac clean --ide --force
   Should also remove CLAUDE.md / AGENTS.md if present
4. Run: oac --help
   Should show 'clean' in the command list
5. Run: oac clean --help
   Should show --force, --dry-run, --ide options

DEPENDENCIES: none
