# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## What This Is

OmniForge is a Claude Code plugin distributed as its own marketplace. It supports both **GitLab** and **GitHub** with the following skills:
- **omnireview-gitlab** — dispatches 3 parallel AI review agents in isolated git worktrees to adversarially review GitLab MRs
- **omnifix-gitlab** — automates fixing review findings with parallel triage subagents, sequential fixing, verification, and thread resolution
- **omnicreate-gitlab** — automates GitLab MR creation via `glab` CLI with auto-populated title/description from commits
- **omnicheck-gitlab** — checks whether requested MR changes have been applied by analyzing the diff against all discussion threads; posts nudge replies on unaddressed findings
- **omnireview-github** — same as omnireview-gitlab but for GitHub PRs via `gh` CLI
- **omnifix-github** — same as omnifix-gitlab but for GitHub PRs
- **omnicreate-github** — automates GitHub PR creation via `gh` CLI
- **omnicheck-github** — same as omnicheck-gitlab but for GitHub PRs

## Repository Layout

This repo has two layers: the **marketplace root** and the **plugin** inside it.

```
/                                    ← Marketplace root
  .claude-plugin/marketplace.json       ← Points to ./plugins/omniforge
  plugins/omniforge/                    ← THE PLUGIN
    .claude-plugin/plugin.json
    .mcp.json                           ← Spawns the MCP server via uv
    skills/
      omnireview-gitlab/                ← GitLab review skill (7-phase)
        SKILL.md
        references/                     ← 5 files: 3 agent prompts + consolidation guide + posting guide
      omnifix-gitlab/                   ← GitLab fix skill (7-phase)
        SKILL.md
        references/                     ← 5 files: 2 agent prompts + approval guide + commit/post guide
      omnicreate-gitlab/                ← GitLab MR creation skill
        SKILL.md
      omnicheck-gitlab/                 ← GitLab check skill (5-phase)
        SKILL.md
        references/                     ← 2 files: analysis agent prompt + nudge guide
      omnireview-github/                ← GitHub review skill (7-phase)
        SKILL.md
      omnifix-github/                   ← GitHub fix skill (7-phase)
        SKILL.md
      omnicreate-github/                ← GitHub PR creation skill
        SKILL.md
      omnicheck-github/                 ← GitHub check skill (5-phase)
        SKILL.md
    tools/omniforge_mcp_server.py       ← Python MCP server (FastMCP, GitLab + GitHub tools)
    tests/                              ← Unit tests
```

The marketplace wrapper exists because `claude plugin marketplace add` requires plugins in subdirectories — it doesn't support a plugin at repo root.

## Commands

### Run tests
```bash
cd plugins/omniforge && python -m pytest tests/ -v
```

### Run a single test
```bash
cd plugins/omniforge && python -m pytest tests/test_discussions.py::TestFetchMrDiscussions::test_success -v
```

### Start MCP server manually (for testing)
```bash
uv run --with "mcp[cli]" python3 plugins/omniforge/tools/omniforge_mcp_server.py
```

### Load plugin locally (without installing)
```bash
claude --plugin-dir plugins/omniforge
```

### Install as marketplace plugin
```bash
claude plugin marketplace add https://github.com/nexiouscaliver/OmniForge.git
claude plugin install omniforge@omniforge-marketplace
```

## Architecture

### Two Skills

**omnireview-gitlab** (review): Gather → Isolate → Dispatch 3 agents → Consolidate → Report → Act → Cleanup
**omnifix-gitlab** (fix): Gather → Triage (parallel) → Approve → Fix → Verify → Post → Cleanup

Both skills support MCP tools (plugin install) with bash fallback (personal skill install).

### MCP Server (`tools/omniforge_mcp_server.py`)

Single-file FastMCP server with 14 tools. The structure follows a pattern:

- **Validators** (`validate_mr_id`, `validate_repo_root`, `validate_branch_name`) — called at the top of every tool function
- **`run_subprocess`** (aliased as `run_exec`) — all external commands go through this. Uses `create_subprocess_exec` (argument list, never shell), `stdin=DEVNULL` (prevents MCP pipe inheritance), and `asyncio.wait_for` timeout
- **Helpers** (`extract_changed_files`, `parse_commits`, `truncate_diff_if_needed`, `parse_diff_line_map`) — pure functions for parsing
- **Tool implementations** — async `_function` functions that do the actual work, return dicts
- **FastMCP wrappers** — thin `@mcp_server.tool()` decorated functions that call internal implementations and `json.dumps` the result
- **Entry point** — `mcp_server.run()` at the bottom

### MCP Tools

The MCP server provides platform-specific tools for both GitLab and GitHub. Worktree tools are shared.

**GitLab Tools (glab CLI):**

| Tool | Used By |
|------|---------|
| `fetch_mr_data` | Review + Fix |
| `create_review_worktrees` | Review (shared) |
| `cleanup_review_worktrees` | Review (shared) |
| `post_full_review` | Review |
| `post_review_summary` | Review + Fix |
| `post_inline_thread` | Review |
| `create_linked_issue` | Review + Fix |
| `map_diff_lines` | Review + Fix (shared, pure function) |
| `fetch_mr_discussions` | Fix |
| `reply_to_discussion` | Fix |
| `resolve_discussion` | Fix |
| `cleanup_omnifix_worktrees` | Fix (shared) |
| `create_gitlab_mr` | Create |
| `approve_mr` | Check |

**GitHub Tools (gh CLI):**

| Tool | Used By |
|------|---------|
| `fetch_pr_data` | Review + Fix |
| `post_pr_full_review` | Review |
| `post_pr_review_summary` | Review + Fix |
| `post_pr_inline_thread` | Review |
| `fetch_pr_discussions` | Fix |
| `reply_to_pr_comment` | Fix |
| `create_github_pr` | Create |

**Shared helpers:** `_detect_platform`, `_resolve_main_repo_root`, `_get_github_repo_id`

### Key Invariant: `./references/` Paths

Each SKILL.md references its supporting files as `./references/filename.md`. These paths are relative to the skill directory (where SKILL.md lives), NOT relative to the repo root. If you move SKILL.md, the references break.

## Testing

Tests mock `run_exec` via `unittest.mock.patch("omniforge_mcp_server.run_exec")`. Test files use `sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'tools'))` to import from the tools directory.

When adding new MCP tools: write the `_internal` implementation function first with tests mocking `run_exec`, then add the thin `@mcp_server.tool()` wrapper.

## Security Constraints

- All subprocess calls MUST use `create_subprocess_exec` (never `create_subprocess_shell`)
- All subprocess calls MUST include `stdin=asyncio.subprocess.DEVNULL`
- All tool functions MUST validate inputs before any subprocess call
- The MCP server MUST NOT write non-JSON-RPC content to stdout
- Posted MR comments MUST NOT contain AI attribution

## Git Workflow

- Do not push to origin without explicit permission
- Use Shahil Kadia as commit author name
- No Claude/AI attribution in commits or MR comments
- Use `glab` for GitLab operations (never `gh`)
