---
Scanned 9/1/2026
Install to Claude Code
npx -y skills add Julian0444/omnicursor --skill onex-hostile-reviewer --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Onex Hostile Reviewer?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/julian0444-onex-hostile-reviewer)More formats (shields.io, HTML) on the badges page.
---
name: "onex-hostile-reviewer"
description: >-
---
disable-model-invocation: true
---
# onex-hostile-reviewer
---
description: Multi-model adversarial code review (Gemini, Codex, Qwen3-Coder, DeepSeek-R1, Claude) with weighted-union finding aggregation and iterative convergence. Cannot rubber-stamp. Use --static for static-analysis-only mode (dead code, missing error handling, stubs, Kafka wiring, schema mismatches, hardcoded values, missing tests).
mode: both
version: 4.0.0
level: intermediate
debug: false
category: review
tags:
- review
- adversarial
- pr
- plan
- multi-model
- quality
- risk
- convergence
- static-analysis
author: OmniClaude Team
args:
- name: pr
description: PR number to review (mutually exclusive with --file). Not used in --static mode.
required: false
- name: repo
description: Target GitHub repo (e.g., OmniNode-ai/omniclaude). Required with --pr.
required: false
- name: file
description: "Path to a plan file to review (mutually exclusive with --pr). Alias: --plan-path. Not used in --static mode."
required: false
- name: plan-path
description: "Alias for --file: path to a plan or design document to review adversarially (mutually exclusive with --pr)"
required: false
- name: ticket_id
description: Linear ticket ID for loading TCB constraints
required: false
- name: models
description: Comma-separated model list (default codex,deepseek-r1). Available models are codex, deepseek-r1, qwen3-coder, qwen3-14b.
required: false
- name: passes
description: "Fixed number of passes to run. Default: iterates until 2 consecutive clean passes. Use --passes 1 for single-pass mode (backwards compat)."
required: false
- name: gate
description: "Gate mode: run 3 parallel review agents (scope, correctness, conventions) and output a structured pass/fail/block verdict suitable for merge gating. Mutually exclusive with --file."
required: false
- name: strict
description: "In --gate mode: block on MINOR+ findings (default blocks on MAJOR+)"
required: false
- name: static
description: "Static-analysis-only mode. Runs 7 code quality checks (dead code, missing error handling, stubs shipped, missing Kafka wiring, schema mismatches, hardcoded values, missing tests) without adversarial multi-model review. Use --repos and --categories to scope the scan."
required: false
- name: repos
description: "Comma-separated repo names to scan in --static mode (default: all Python repos in the OmniNode-ai org)"
required: false
- name: categories
description: "Comma-separated finding categories for --static mode: dead-code,missing-error-handling,stubs-shipped,missing-kafka-wiring,schema-mismatches,hardcoded-values,missing-tests (default: all)"
required: false
- name: dry-run
description: "In --static mode: scan and report only, no tickets created. First static run defaults to --dry-run."
required: false
- name: ticket
description: "In --static mode: create Linear tickets for findings (hard cap 10 per run)"
required: false
- name: max-tickets
description: "In --static mode: hard cap on tickets created per run (default: 10)"
required: false
---
# hostile-reviewer
**Announce at start:** "I'm using the onex-hostile-reviewer skill."
## Architecture
```
SKILL.md -> thin shell (this file)
node -> omniintelligence/src/omniintelligence/review_pairing/ (multi-model review)
entry -> omniintelligence.review_pairing.cli_review (CLI)
```
Node invocation (working directory must be the `omniintelligence` repo root):
```bash
uv run python -m omniintelligence.review_pairing.cli_review \ # local-path-ok: omniintelligence direct CLI invocation until OMN-8770 onex run migration
--pr <N> --repo <owner/repo> --model codex --model deepseek-r1 2>/dev/null
```
## Dispatch Surface
**Target**: Agent Teams + Local LLM
## Description
Multi-model adversarial review with **iterative convergence**. The skill loops automatically,
applying fixes after each pass, until **2 consecutive passes produce nothing above NIT severity**.
A single pass catches ~60% of issues; fixes from pass N introduce new issues caught in pass N+1.
Iterating to convergence eliminates this false-completeness problem.
Calls Codex CLI (primary, ChatGPT-class model) and local LLMs (DeepSeek-R1) for independent
cross-check. Returns all findings with per-model attribution. Output is MANDATORY -- the skill
always produces a result artifact even when verdict is `clean` (empty `findings` array is valid
for `clean`). Cannot rubber-stamp without running the models.
Codex CLI is the primary reviewer because it produces high signal-to-noise findings
(typically 5-15 precise structural observations vs 40-55 pattern-level noise from local
models alone). DeepSeek-R1 provides a local reasoning cross-check. Additional local
models (qwen3-coder, qwen3-14b) are available via `--models` override when broader
coverage is needed.
This skill consolidates the former `hostile-reviewer` (PR-only, Claude-only, exactly-2-risks),
`external-model-review` (file-only, multi-model), and `code-review-sweep` (static analysis)
into a single unified skill.
## Modes
### PR Mode (`--pr <N> --repo <owner/repo>`)
Reviews a PR diff using multi-model adversarial review.
```bash
/hostile-reviewer --pr 433 --repo OmniNode-ai/omniintelligence
```
### File Mode (`--file <path>` or `--plan-path <path>`)
Reviews a plan or design document using multi-model adversarial review.
This replaces the former `/external-model-review` skill.
`--plan-path` is an alias for `--file` — both are accepted and behave identically.
```bash
/hostile-reviewer --file docs/plans/my-plan.md
/hostile-reviewer --plan-path docs/plans/my-plan.md
```
### Gate Mode (`--pr <N> --repo <owner/repo> --gate`)
Merge gate mode. Dispatches 3 parallel review agents (scope, correctness, conventions),
collects structured verdicts, aggregates findings by severity, and produces a structured
`pass`/`fail` gate verdict plus `extra_status` of `passed`/`blocked` for pipeline consumption. This mode absorbs the
former `review_gate` skill.
```bash
/hostile-reviewer --pr 433 --repo OmniNode-ai/omniclaude --gate
/hostile-reviewer --pr 433 --repo OmniNode-ai/omniclaude --gate --strict
```
**Gate verdict output** (`extra_status`):
- `passed`: no blocking findings across all agents
- `blocked`: one or more blocking findings (MAJOR+ in default mode, MINOR+ in `--strict`)
**Requires** `--pr` and `--repo`. Mutually exclusive with `--file`.
**Skill result** (written to `$ONEX_STATE_DIR/skill-results/{context_id}/hostile-reviewer.json`):
| Field | Value |
|-------|-------|
| `skill_name` | `"hostile-reviewer"` |
| `status` | `"success"` (gate passed) / `"partial"` (gate blocked) |
| `extra_status` | `"passed"` / `"blocked"` |
| `extra` | `{"gate_verdict": str, "total_findings": int, "blocking_count": int, "agent_count": 3, "verdicts": [...]}` |
### Static Mode (`--static`)
Runs static analysis checks across repos without adversarial multi-model review.
This replaces the former `/code-review-sweep` skill.
```bash
/hostile-reviewer --static # Full scan all repos (first run = dry-run)
/hostile-reviewer --static --dry-run # Report only
/hostile-reviewer --static --ticket # Create Linear tickets for findings
/hostile-reviewer --static --repos omniclaude,omniintelligence # Scope to specific repos
/hostile-reviewer --static --categories dead-code,stubs-shipped # Scope to specific categories
/hostile-reviewer --static --max-tickets 5 # Lower ticket cap
```
**Finding Categories:**
1. **dead-code** — Module-level unused functions/classes (LLM) + cross-file dead code (vulture, >=80% confidence)
2. **missing-error-handling** — Bare `except:` / `except Exception:` with `pass`
3. **stubs-shipped** — `TODO`/`FIXME`/`NotImplementedError` in non-test source
4. **missing-kafka-wiring** — Topics declared in contract.yaml but not wired in code
5. **schema-mismatches** — Pydantic field mismatches against contract config_keys
6. **hardcoded-values** — IP addresses, port numbers, connection strings in source
7. **missing-tests** — Source modules with no corresponding test file
**State tracking**: `.onex_state/code-review-state.json` tracks file hashes and finding fingerprints to avoid re-scanning unchanged files and dedup findings across runs.
**First-run safety**: The first invocation defaults to `--dry-run` unless explicitly overridden.
**Hard cap**: 10 tickets per run (configurable via `--max-tickets`).
**ModelCodeReviewFinding schema:**
```python
{
"repo": str, # e.g. "omniclaude"
"path": str, # repo-relative path
"line": int, # 0 if whole-file
"category": str, # e.g. "dead-code"
"message": str, # human-readable description
"severity": str, # CRITICAL | ERROR | WARNING | INFO
"confidence": str, # HIGH | MEDIUM | LOW
"fingerprint": str, # dedup key: "{repo}:{path}:{line}:{category}"
"is_new": bool, # not seen in prior run
"ticketed": bool, # ticket was created
}
```
## Execution
### Convergence Loop (default behavior)
The skill iterates until convergence. **Convergence** = 2 consecutive passes where no
finding is above NIT severity. This is the default behavior.
Override with `--passes N` for a fixed number of passes (e.g., `--passes 1` for
single-pass backwards compatibility).
**Algorithm:**
```
consecutive_clean = 0
pass_number = 0
max_passes = args.passes or 10 # safety cap to prevent infinite loops
iteration_history = []
while consecutive_clean < 2 and pass_number < max_passes:
pass_number += 1
start_time = now()
# 1. Run multi-model review
result = run_review(mode, target, models)
# 2. Count findings above NIT
above_nit = [f for f in result.findings if f.severity in (CRITICAL, MAJOR, MINOR)]
# 3. Record pass in iteration history
iteration_history.append({
"pass": pass_number,
"duration_s": elapsed(start_time),
"verdict": result.verdict,
"counts": {
"CRITICAL": count(CRITICAL),
"MAJOR": count(MAJOR),
"MINOR": count(MINOR),
"NIT": count(NIT)
},
"models_used": result.models_succeeded,
"action": "clean" if not above_nit else "fix_and_rerun"
})
# 4. Check convergence
if not above_nit and result.verdict != "degraded":
consecutive_clean += 1
else:
consecutive_clean = 0
# 5. If not converged, apply fixes and loop
if consecutive_clean < 2 and above_nit:
apply_fixes(above_nit) # dispatch to polymorphic-agent for code changes
# If --passes N was specified and we hit it, stop regardless
if args.passes and pass_number >= args.passes:
break
```
**Safety cap**: The loop runs at most 10 passes (configurable via `--passes`). If
convergence is not reached in 10 passes, the skill reports partial convergence with
the full iteration history.
### Single Pass Steps
Each pass within the loop executes:
1. Determine mode (PR or file) from arguments.
2. Invoke the multi-model review CLI:
**PR mode (default models):**
```bash
uv run python -m omniintelligence.review_pairing.cli_review \ # local-path-ok: omniintelligence direct CLI invocation until OMN-8770 onex run migration
--pr <N> --repo <owner/repo> --model codex --model deepseek-r1 2>/dev/null
```
**File mode (default models):**
```bash
uv run python -m omniintelligence.review_pairing.cli_review \ # local-path-ok: omniintelligence direct CLI invocation until OMN-8770 onex run migration
--file <path> --model codex --model deepseek-r1 2>/dev/null
```
When `--models` is provided, expand into repeated `--model` args dynamically:
```bash
# Example: --models deepseek-r1,qwen3-14b,codex
uv run python -m omniintelligence.review_pairing.cli_review \ # local-path-ok: omniintelligence direct CLI invocation until OMN-8770 onex run migration
--pr <N> --repo <owner/repo> --model deepseek-r1 --model qwen3-14b --model codex 2>/dev/null
```
3. Parse the `ModelMultiReviewResult` JSON from stdout.
4. If `--ticket_id` is provided, load TCB constraints from
`$ONEX_STATE_DIR/tcb/{ticket_id}/bundle.json` and cross-reference findings
against TCB invariants.
### Fix Application (between passes)
When a pass produces findings above NIT:
1. Report findings to the caller.
2. Dispatch a polymorphic-agent to apply fixes for all CRITICAL, MAJOR, and MINOR findings.
3. Stage the fixes (but do not commit -- the caller controls commits).
4. Re-run the review on the updated code.
### Post-Convergence
After convergence (or max passes reached):
1. Post the final findings summary as a GitHub PR review comment (PR mode only).
2. Persist results including full iteration history.
3. Emit completion event.
## Default Persona
All reviews (file-mode and PR-mode) use the **analytical-strict** persona by default.
This persona enforces:
- PhD-level domain expertise posture
- Journal-critique format (no praise, no qualifiers)
- Contract-semantics focus: invariant gaps, integration boundary failures, missing idempotency guards
- Specific "what to change and why" per finding (three sentences max)
- Skeptical analytical tone: nothing is assumed correct unless proven
Persona file: `omniintelligence/review_pairing/personas/analytical-strict.md`
To override: pass `--persona <name>` where `<name>` matches a file in
`omniintelligence/review_pairing/personas/`. To use no persona: pass
`--system-prompt /dev/null` (bypasses persona loading).
## Model Selection
Default models: `codex,deepseek-r1`
Codex CLI is the primary reviewer (ChatGPT-class model, highest signal-to-noise ratio).
DeepSeek-R1 provides a local reasoning cross-check without network dependency.
Override with `--models`:
```bash
/hostile-reviewer --pr 433 --repo OmniNode-ai/omniintelligence --models codex,qwen3-coder,deepseek-r1
```
Available models (see omniintelligence `review_pairing/models.py` for registry):
- `codex` -- Codex CLI (ChatGPT-class model, requires `codex` binary in PATH)
- `deepseek-r1` -- DeepSeek-R1-Distill-Qwen-32B (M2 Ultra, reasoning/code review)
- `qwen3-coder` -- Qwen3-Coder-30B-A3B AWQ-4bit (RTX 5090, long context code)
- `qwen3-14b` -- Qwen3-14B-AWQ (RTX 4090, mid-tier)
## Output Format
### Per-Model Status
For each model, report:
- Model name
- Status (succeeded / failed with error)
- Finding count by severity
### Disagreement Rendering
When models materially disagree on a major issue (one flags CRITICAL/MAJOR,
the other is silent or disagrees), surface that disagreement explicitly
BEFORE the detailed grouped findings:
```
DISAGREEMENT: DeepSeek-R1 flags "Missing retry logic" as CRITICAL.
Codex did not flag this issue. Review the evidence below.
```
### Grouped Findings
Present findings grouped by source model:
```
## DeepSeek-R1 (4 findings)
1. [CRITICAL] Missing retry logic
Category: architecture
Evidence: ...
Proposed fix: ...
## Codex (6 findings)
...
```
### Iteration History Table
The final output MUST include an iteration history table summarizing all passes:
```
## Iteration History
| Pass | Duration | Verdict | CRIT | MAJ | MIN | NIT | Models | Action |
|------|----------|----------------|------|-----|-----|-----|--------------|---------------|
| 1 | 45.2s | blocking_issue | 1 | 3 | 2 | 4 | codex, dr1 | fix_and_rerun |
| 2 | 38.7s | risks_noted | 0 | 1 | 1 | 2 | codex, dr1 | fix_and_rerun |
| 3 | 32.1s | clean | 0 | 0 | 0 | 1 | codex, dr1 | clean (1/2) |
| 4 | 30.5s | risks_noted | 0 | 1 | 0 | 0 | codex, dr1 | fix_and_rerun |
| 5 | 29.8s | clean | 0 | 0 | 0 | 0 | codex, dr1 | clean (2/2) |
Convergence: ACHIEVED after 5 passes (2 consecutive clean)
Total duration: 176.3s
Total findings resolved: 27
```
This table is the primary human-readable output of the iterative review. It is always
rendered even when `--passes 1` is used (showing a single row).
### Degraded-Mode Visibility
- If one model succeeds and one fails, report partial success explicitly.
- If ALL models fail, report failure and return gracefully. Do not block
the calling workflow.
- Never silently omit a failed model from the output.
## Severity Mapping
Findings use canonical severity levels:
- **CRITICAL** (ERROR): Security, data loss, architectural redesign required
- **MAJOR** (WARNING): Performance, missing error handling, incomplete tests
- **MINOR** (INFO): Code quality, documentation gaps, edge cases
- **NIT** (HINT): Formatting, naming, minor refactoring
## Convergence Criteria
Default: **2 consecutive clean passes** (no findings above NIT severity).
A "clean pass" means:
- At least one model succeeded (not degraded)
- No CRITICAL, MAJOR, or MINOR findings across all models
- NIT findings are allowed and do not reset the consecutive counter
The 2-consecutive requirement prevents false convergence from a single lucky pass.
Evidence from the ModelPlanContract review (5 passes, 27 total findings) shows that
pass N fixes routinely introduce 2-4 new issues caught in pass N+1.
Override: `--passes N` sets a fixed pass count. The skill runs exactly N passes and
reports the final state regardless of convergence. Use `--passes 1` for single-pass
backwards compatibility.
## Verdict Determination
Per-pass verdict (unchanged from v2):
- `clean`: no findings above MINOR severity across all models (findings array may be empty or contain only NIT/MINOR entries). Requires at least one model to have succeeded.
- `risks_noted`: MAJOR findings exist but are not blocking -- implementer should address
- `blocking_issue`: at least one CRITICAL finding from any model -- must fix before merge
- `degraded`: ALL requested models failed. No findings were produced. This is NOT `clean` -- it means review could not be performed. The calling workflow decides whether to proceed or block.
Overall convergence verdict (new in v3):
- `converged`: 2 consecutive clean passes achieved. The code is stable.
- `partially_converged`: max passes reached with fewer than 2 consecutive clean passes. Findings may still exist.
- `not_converged`: fixed-pass mode (`--passes N`) completed without achieving convergence. Informational only.
## When Called
- **ticket-pipeline Phase 2.4** (between local_review and mergeability_gate) -- PR mode
- **ticket-pipeline Phase 5.5 (review_gate)** -- `--gate` mode (replaces former review_gate skill)
- **design-to-plan Phase 2c** (after R1-R7 convergence) -- file mode
- **Standalone** for any PR or plan file
## Token Budget
**`2>/dev/null` is MANDATORY in all `prompt.md` bash blocks that invoke the aggregator.**
Each model (Gemini, Codex, Qwen3-Coder, DeepSeek-R1) emits hundreds to thousands of
tokens of chain-of-thought, progress output, and prose to stderr before producing its
JSON finding. Without `2>/dev/null`, every model's verbose output enters Claude's context
window on every review run, making multi-model review unviably expensive (~5,000–15,000
tokens per invocation instead of ~500).
The stdout-only JSON contract is what makes multi-model review viable:
- **stdout**: compact aggregated JSON (~500 tokens) — Claude Code sees this
- **stderr**: all model verbose output — silenced by `2>/dev/null`, never enters context
- **event bus**: full per-model raw findings — captured here for observability via
`hostile.reviewer.completed` / `hostile.reviewer.failed` events (OMN-6188)
**Do not remove `2>/dev/null` from prompt.md.** If you need to debug model output,
redirect stderr to a temp file instead: `2>/tmp/hostile-reviewer-debug.log`.
## Persisted Artifact
Write result to `$ONEX_STATE_DIR/skill-results/{context_id}/hostile-reviewer.json`:
```json
{
"mode": "pr|file",
"target": "<pr_number or file_path>",
"convergence_mode": "iterative|fixed",
"passes_requested": null,
"total_passes": 5,
"consecutive_clean_at_end": 2,
"convergence_verdict": "converged|partially_converged|not_converged",
"iteration_history": [
{
"pass": 1,
"duration_s": 45.2,
"verdict": "blocking_issue",
"counts": {"CRITICAL": 1, "MAJOR": 3, "MINOR": 2, "NIT": 4},
"models_used": ["codex", "deepseek-r1"],
"action": "fix_and_rerun"
},
{
"pass": 2,
"duration_s": 38.7,
"verdict": "risks_noted",
"counts": {"CRITICAL": 0, "MAJOR": 1, "MINOR": 1, "NIT": 2},
"models_used": ["codex", "deepseek-r1"],
"action": "fix_and_rerun"
},
{
"pass": 3,
"duration_s": 32.1,
"verdict": "clean",
"counts": {"CRITICAL": 0, "MAJOR": 0, "MINOR": 0, "NIT": 1},
"models_used": ["codex", "deepseek-r1"],
"action": "clean"
},
{
"pass": 4,
"duration_s": 30.5,
"verdict": "risks_noted",
"counts": {"CRITICAL": 0, "MAJOR": 1, "MINOR": 0, "NIT": 0},
"models_used": ["codex", "deepseek-r1"],
"action": "fix_and_rerun"
},
{
"pass": 5,
"duration_s": 29.8,
"verdict": "clean",
"counts": {"CRITICAL": 0, "MAJOR": 0, "MINOR": 0, "NIT": 0},
"models_used": ["codex", "deepseek-r1"],
"action": "clean"
}
],
"models_requested": ["gemini", "codex", "qwen3-coder", "deepseek-r1"],
"models_run": ["gemini", "codex", "qwen3-coder", "deepseek-r1"],
"models_succeeded": ["gemini", "codex", "qwen3-coder", "deepseek-r1"],
"models_failed": [],
"per_model_severity_counts": {
"codex": {"CRITICAL": 0, "MAJOR": 0, "MINOR": 0, "NIT": 0},
"deepseek-r1": {"CRITICAL": 0, "MAJOR": 0, "MINOR": 0, "NIT": 0}
},
"findings": [],
"disagreements": [],
"invariant_checklist": [
{"invariant": "...", "status": "PASS|FAIL|NOT_CHECKED"}
],
"overall_verdict": "clean|risks_noted|blocking_issue|degraded"
}
```
**Note**: `findings`, `per_model_severity_counts`, and `disagreements` reflect the **final pass only**.
The full per-pass breakdown is in `iteration_history`.
Post result as a PR review comment (PR mode). For `blocking_issue`, use REQUEST_CHANGES;
otherwise use COMMENT.
## Static Mode Artifact
In `--static` mode, write result to `$ONEX_STATE_DIR/skill-results/{context_id}/hostile-reviewer-static.json`:
```json
{
"mode": "static",
"run_id": "20260326-140000-a3f",
"repos_scanned": 8,
"files_scanned": 142,
"files_skipped_unchanged": 87,
"total_findings": 23,
"new_findings": 8,
"by_category": {
"dead-code": 5,
"missing-error-handling": 3,
"stubs-shipped": 4,
"missing-kafka-wiring": 2,
"schema-mismatches": 1,
"hardcoded-values": 3,
"missing-tests": 5
},
"tickets_created": 8,
"ticket_cap_hit": false,
"status": "clean | findings | partial | error"
}
```
Status values for static mode:
- `clean` — zero findings
- `findings` — findings reported (tickets created if `--ticket` was set)
- `partial` — some repos failed to scan
- `error` — scan failures prevented completion
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!