{"_id":"@capybearista/opencode-adversarial-review","_rev":"3-728a192565c8cff8f6fa3501988cb931","name":"@capybearista/opencode-adversarial-review","dist-tags":{"latest":"2.0.0"},"versions":{"0.1.0":{"name":"@capybearista/opencode-adversarial-review","version":"0.1.0","author":{"name":"capyBearista","email":"capybearista@gmail.com"},"license":"MPL-2.0","_id":"@capybearista/opencode-adversarial-review@0.1.0","maintainers":[{"name":"capybearista","email":"capybearista@gmail.com"}],"dist":{"shasum":"d1c07f5f604cd06a90bc61a4d7baed999641ab58","tarball":"https://registry.npmjs.org/@capybearista/opencode-adversarial-review/-/opencode-adversarial-review-0.1.0.tgz","fileCount":6,"integrity":"sha512-EsRSz9svnKqG+hbxb16x9x1oElxbZLMbVZuXOqtq9aTi/uWyIisgSfPV5+R4QBHK0uKdxTalvRaQY9k5RvVT3g==","signatures":[{"sig":"MEUCIB9pdn+GTgrHz88Qa0PrdrfqgfSFLk0V0BPOBQgvQEfxAiEAgbePp46BFeUN/2Wr22t/an1iGaf8Yj4SvXl8KAb3+MA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":35192},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"fa0c09d7434a367495efbf772e59734b78f9aa49","scripts":{"ci":"bunx @biomejs/biome ci .","lint":"bunx @biomejs/biome check .","test":"bun test","build":"tsc","check":"bunx @biomejs/biome check --write .","typecheck":"tsc --noEmit"},"_npmUser":{"name":"capybearista","email":"capybearista@gmail.com"},"_npmVersion":"11.13.0","description":"Adversarial code review plugin","directories":{},"_nodeVersion":"22.18.0","_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest","typescript":"^6.0.3","@tsconfig/node22":"^22.0.0","@opencode-ai/plugin":">=1.14.0"},"peerDependencies":{"@opencode-ai/plugin":">=1.14.0"},"_npmOperationalInternal":{"tmp":"tmp/opencode-adversarial-review_0.1.0_1778357133442_0.4891847283575521","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@capybearista/opencode-adversarial-review","version":"1.0.0","author":{"name":"capyBearista","email":"capybearista@gmail.com"},"license":"MPL-2.0","_id":"@capybearista/opencode-adversarial-review@1.0.0","maintainers":[{"name":"capybearista","email":"capybearista@gmail.com"}],"homepage":"https://github.com/capyBearista/opencode-plugins#readme","bugs":{"url":"https://github.com/capyBearista/opencode-plugins/issues"},"dist":{"shasum":"bfe1eda5eb27b9cdc333e8700f0cfa2930dca949","tarball":"https://registry.npmjs.org/@capybearista/opencode-adversarial-review/-/opencode-adversarial-review-1.0.0.tgz","fileCount":6,"integrity":"sha512-P01EkGTYzwcvt3OKV8KphbCgvwA2tzeoCoLxBKf0GqYtyfcNt7yd3clmY4ycc/99j4fA1oe6Au9Q8dMz3qzhEw==","signatures":[{"sig":"MEUCIQDVOI42OoBEseBwyBwvF3VcqxKhAPYw0geP42EvK0t3sAIgeh1AZV3st0damS4UHvXgmSsMikz/pKjag0axjbi43I8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@capybearista%2fopencode-adversarial-review@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":35357},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"3dcbf17ffc84d07ef468273daba91c36e0469f53","scripts":{"ci":"bunx @biomejs/biome ci .","lint":"bunx @biomejs/biome check .","test":"bun test","build":"tsc","check":"bunx @biomejs/biome check --write .","typecheck":"tsc --noEmit"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:52b53173-111b-49b8-8e3e-eba28d4449b3"}},"repository":{"url":"git+https://github.com/capyBearista/opencode-plugins.git","type":"git","directory":"packages/opencode-adversarial-review"},"_npmVersion":"11.11.0","description":"Adversarial code review plugin","directories":{},"_nodeVersion":"24.14.1","_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest","typescript":"^6.0.3","@tsconfig/node22":"^22.0.0","@opencode-ai/plugin":">=1.14.0"},"peerDependencies":{"@opencode-ai/plugin":">=1.14.0"},"_npmOperationalInternal":{"tmp":"tmp/opencode-adversarial-review_1.0.0_1778358017836_0.03301939658784736","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"_id":"@capybearista/opencode-adversarial-review@2.0.0","bugs":{"url":"https://github.com/capyBearista/opencode-plugins/issues"},"dist":{"shasum":"e5ba6ef351b3818246b53fb702f23746bcb2226c","tarball":"https://registry.npmjs.org/@capybearista/opencode-adversarial-review/-/opencode-adversarial-review-2.0.0.tgz","fileCount":12,"integrity":"sha512-yqKXiNeLNlQekXCNfvHS5WUvJmOOOCH7k7v5YylFWMx8OyfLySHh8ShZNcImJrcUzBId6EEgPWkmK1YE0hxWgQ==","signatures":[{"sig":"MEUCIG24+RnAn4JS4E2BQMWlb27sS7duaJUoXlil9ka61/C9AiEAroEZbTRiYHh7mpW4nsWTf8LBBYt4Eg5Y5bthVdoaVJc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIF3P+zh+H99SYZlPTK5w1yeIF6l+AhKsU6lefkYeV6v6AiBOX4uyZbFMPKBquKQtiYtQeH384BxkAj+xomT0qgZRWg=="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@capybearista%2fopencode-adversarial-review@2.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":126520},"main":"./dist/index.js","name":"@capybearista/opencode-adversarial-review","type":"module","types":"./dist/index.d.ts","author":{"name":"capyBearista","email":"capybearista@gmail.com"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"gitHead":"63ea274ffdc21f2ffcd252bfbca1bdb4b5643c56","license":"MPL-2.0","scripts":{"ci":"bunx @biomejs/biome ci .","lint":"bunx @biomejs/biome check .","test":"bun test","build":"rm -rf dist && tsc","check":"bunx @biomejs/biome check --write .","smoke":"bun run build && bun scripts/smoke-built.ts","start":"node server.js","typecheck":"tsc --noEmit"},"version":"2.0.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:52b53173-111b-49b8-8e3e-eba28d4449b3"}},"homepage":"https://github.com/capyBearista/opencode-plugins#readme","repository":{"url":"git+https://github.com/capyBearista/opencode-plugins.git","type":"git","directory":"packages/opencode-adversarial-review"},"_npmVersion":"11.19.0","description":"Two code review agents for OpenCode — an adversarial reviewer (/adversarial-review) that challenges the implementation, and a constructive reviewer (/constructive-review) focused on correctness and suggestions","directories":{},"maintainers":[{"name":"capybearista","email":"capybearista@gmail.com"}],"_nodeVersion":"24.11.1","_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest","typescript":"^6.0.3","@opencode/plugin":"2.0.2","@tsconfig/node22":"^22.0.0"},"peerDependencies":{"@opencode/plugin":"2.0.2"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/opencode-adversarial-review_2.0.0_1790494590564_0.7531892249381109"}}},"time":{"created":"2026-05-09T20:05:33.332Z","modified":"2026-09-27T07:36:30.989Z","0.1.0":"2026-05-09T20:05:33.566Z","1.0.0":"2026-05-09T20:20:17.996Z","2.0.0":"2026-09-27T07:36:30.644Z"},"bugs":{"url":"https://github.com/capyBearista/opencode-plugins/issues"},"author":{"name":"capyBearista","email":"capybearista@gmail.com"},"license":"MPL-2.0","homepage":"https://github.com/capyBearista/opencode-plugins#readme","repository":{"url":"git+https://github.com/capyBearista/opencode-plugins.git","type":"git","directory":"packages/opencode-adversarial-review"},"description":"Two code review agents for OpenCode — an adversarial reviewer (/adversarial-review) that challenges the implementation, and a constructive reviewer (/constructive-review) focused on correctness and suggestions","maintainers":[{"name":"capybearista","email":"capybearista@gmail.com"}],"readme":"# opencode-adversarial-review\n\n<p align=\"center\">Unbiased challenges and reviews for your code</p>\n<p align=\"center\">\n  <a href=\"https://www.npmjs.com/package/@capybearista/opencode-adversarial-review\"><img alt=\"npm\" src=\"https://img.shields.io/npm/v/@capybearista/opencode-adversarial-review?style=flat-square&color=8d60e6\" /></a>\n  <a href=\"https://www.npmjs.com/package/@capybearista/opencode-adversarial-review\"><img alt=\"npm\" src=\"https://img.shields.io/npm/dm/@capybearista/opencode-adversarial-review?style=flat-square&color=6067e6\" /></a>\n  <a href=\"https://opencode.ai\"><img alt=\"opencode\" src=\"https://img.shields.io/badge/OpenCode-Plugin-orange?style=flat-square&color=60a5e6\" /></a>\n  <a href=\"https://opensource.org/licenses/MPL-2.0\"><img alt=\"license\" src=\"https://img.shields.io/badge/License-MPL--2.0-blue.svg?style=flat-square&color=60dfe6\" /></a>\n</p>\n\n---\n\n## Why?\n\nTwo code review agents with a clean-context subagent each, so reviews are unbiased by conversation history: an **adversarial reviewer** that challenges approach and design choices (modeled on the Codex CLI's review system), and a **constructive reviewer** that checks correctness first and suggests improvements.\n\n## Philosophy: Extending OpenCode\n\nOpenCode is designed to be highly extensible. This plugin hooks into the review lifecycle to add adversarial and constructive passes directly to your workflow.\n\n### Architecture\n\nOne config drives two sandboxed subagents: agents register in memory, commands install to disk, prompts ship with the code.\n\nOne `REVIEWERS` config drives both agents; only identity, command file, and prompt differ:\n\n- **Agents**: setup registers the hidden `adversarial-reviewer` and `constructive-reviewer` subagents through `agent.transform`. Nothing is written to your agents directory.\n- **Commands**: setup installs `commands/adversarial-review.md` and `commands/constructive-review.md` into your OpenCode config directory. The host discovers them as `/adversarial-review` and `/constructive-review` and routes each to its reviewer with `subagent: true`.\n- **Prompts**: `src/prompt.ts` holds both system prompts; `src/prompts/adversarial-review.md` and `src/prompts/constructive-review.md` are their reference copies. All review doctrine — target selection, evidence rules, output contract — lives there, never in the command templates.\n\n```mermaid\ngraph TB\n    subgraph Host [OpenCode Host]\n        User([User]) -->|\"/adversarial-review / /constructive-review\"| Command[Installed Command Templates]\n        Command -->|\"$ARGUMENTS + five shell blocks\"| Reviewer\n    end\n\n    subgraph Plugin [Plugin]\n        Setup[setup] -->|agent.transform| Reviewer{\"adversarial-reviewer<br/>constructive-reviewer<br/>hidden subagents\"}\n        Setup -->|\"atomic install; stamped refresh\"| Command\n    end\n\n    subgraph Review [Review Session]\n        Reviewer -->|self-collected evidence| Tools[read / grep / glob / git / gh]\n        Tools --> Reviewer\n        Reviewer -->|\"requested output: JSON / Markdown\"| User\n    end\n\n    classDef host fill:#bbf,stroke:#333,stroke-width:2px;\n    classDef plugin fill:#dfd,stroke:#333,stroke-width:1px,stroke-dasharray: 5 5;\n    classDef adversary fill:#f9f,stroke:#333,stroke-width:2px;\n\n    class Host host;\n    class Plugin plugin;\n    class Review adversary;\n```\n\n## Features\n\n- **Two reviewers**: adversarial (reasons *not* to ship) and constructive (correctness first, then suggestions).\n- **Reviewer-collected evidence**: changed files, untracked files, and branch diffs are inspected with read-only tools; only verified findings are reported.\n- **Auto-installed commands**: both slash commands are written on first setup; stamped files refresh on `/reload`, user-owned edits are preserved (see note below).\n- **Targets**: `--scope`, `--base`, bare commit SHA, or PR URL/number on both commands.\n- **No pinned temperature or model**: both inherit from the invoking chain.\n\n## Requirements\n\n- Tested on GNU/Linux with a Bash-compatible shell. Elsewhere the five snapshot blocks may render partially; the reviewer is told the snapshot may be incomplete and self-collects the rest.\n- `git` on `PATH`; `gh` installed and authenticated only for pull request targets.\n- A writable `<config>/commands/` directory (see Install).\n\n## Install\n\nTargets the V2 Promise plugin API (`@opencode/plugin` **2.0.2**); not compatible with a V1 host. Add it under the plural `\"plugins\"` key:\n\n```json\n{\n  \"plugins\": [\"@capybearista/opencode-adversarial-review@latest\"]\n}\n```\n\nServer entry only, so `cli.json` needs no entry. Or via CLI: `opencode2 plugin add @capybearista/opencode-adversarial-review`. V1 hosts use the singular `\"plugin\"` key and the V1 line — see the [V1 plugin guide](../../docs/v1-plugins.md).\n\n> [!IMPORTANT]\n> The V2 port is unreleased until `2.0.0` publishes. Until then `@latest` still resolves to the V1 `1.0.0` line, which requires a V1 host. This package publishes `2.0.0` to the `latest` tag, not the `opencode2` channel.\n\nOn setup, both command files install at `<OPENCODE_CONFIG_DIR ?? ~/.config/opencode>/commands/{adversarial-review.md,constructive-review.md}`. The directory must already exist; if a file cannot install, setup fails loudly and **neither** agent is registered.\n\n> [!NOTE]\n> The installed command files are managed via a `managed_version` stamp in their frontmatter. Keep the stamp and the file refreshes from the bundled template on `/reload`; remove it to take ownership — the file is then left untouched with a warning. Unknown or newer stamps are likewise preserved (downgrades never clobber). A failure partway can leave the first file as a harmless orphan; it is reconciled on the next `/reload`, and registration still waits for both files. Delete a file and `/reload` to force-reinstall; uninstall the plugin *and* delete both files to fully remove the commands.\n>\n> The same ownership rule cleans up an upgrade leftover: a pre-rename build installed the second command as `commands/review.md` with `agent: reviewer`, an agent this version no longer registers, so the host discovers it as a broken `/review`. Setup removes that exact file only when it carries `agent: reviewer` plus a `managed_version` stamp this build knows; any other `review.md` is preserved, with a warning when it carries the old agent id. Setup never deletes a file on a failed refresh unless its `O_TRUNC` open already ran — an unreadable/unwritable managed file is left intact and setup fails loudly instead.\n\n### Updating\n\n`opencode2 plugin check` / `opencode2 plugin update` move the configured target (restart alone upgrades nothing; stop active sessions first). Command-file refresh follows the stamp rules in the note above.\n\n### Uninstall\n\nRemove the plugin from `\"plugins\"` (or `opencode2 plugin remove @capybearista/opencode-adversarial-review`), then delete both installed command files — plugin removal does not delete them, and the host would otherwise keep discovering commands with no agents behind them.\n\n## Usage\n\nBoth commands accept `--scope auto|working-tree|branch`, `--base <ref>`, a bare commit SHA, or a PR URL/number. A PR URL always wins; otherwise the first bare token decides (all-decimal → PR, 7+ hex chars with a letter → commit); an explicit target beats the flags. `/adversarial-review` treats remaining text as a focus area; `/constructive-review` ignores trailing non-flag text (no focus support).\n\n```bash\n/adversarial-review                  # working tree (or branch, if tree is clean)\n/adversarial-review --scope branch   # current branch since fork point\n/adversarial-review 4f2a9c1e         # a commit\n/adversarial-review 42               # PR #42 (bare number; hex SHAs stay commits)\n/constructive-review --scope working-tree  # constructive pass, working tree only\n/constructive-review --scope branch        # constructive pass, current branch since fork point\n/constructive-review 4f2a9c1e              # constructive pass, a commit\n/constructive-review 42                    # constructive pass, PR #42\n```\n\n## Configuration\n\nNothing is pinned — model and temperature are both inherited. Resolution order for the model: frontmatter `model` (add manually to pin) → agent `model` in OpenCode config → invoking session's model, with its temperature. To pin a reviewer model, set it in `opencode.json`/`opencode.jsonc`:\n\n```jsonc\n{\n  \"agents\": {\n    \"adversarial-reviewer\": { \"model\": \"openrouter/openai/gpt-6-sol\" },\n    \"constructive-reviewer\": { \"model\": \"openrouter/openai/gpt-6-sol\" }\n  }\n}\n```\n\n## Permissions & Security\n\nBoth reviewers are sandboxed and unattended; the single accepted risk is pasted arguments (below). Details:\n\n**Pasted arguments become executable template content.** `$ARGUMENTS` is substituted before the snapshot blocks run, so argument text can execute as shell. Inspect arguments before invoking, and never pass untrusted or pasted Markdown containing backtick blocks.\n\nOne shared sandbox: `edit`/`write`/`patch`, `subagent`, `skill`, `webfetch`/`websearch`, `question` denied (zero ask — reviewers run unattended); shell limited to 13 read-only `git` patterns plus `gh pr view*`/`gh pr diff*` and the `gh auth status*` diagnostic (token-printing and all other `gh` denied); `read`/`grep`/`glob` allowed except `.env`/`.env.*` (`.env.example` allowed, as is `git show <rev>:<path>` of a `.env.example` blob). See `AGENTS.md` for the full rule inventory.\n\n## Troubleshooting\n\n- **Setup failed installing a command file**: create (or fix permissions on) `<config>/commands/`, then `/reload`. A readable-but-unwritable managed file is left untouched, never deleted.\n- **\"Leaving it untouched\" warning**: the file is user-owned or carries an unknown/newer stamp — edit in place, or delete to reinstall.\n- **Broken `/review` after upgrading**: a pre-rename build's `commands/review.md` references the removed `reviewer` agent. Setup removes it when it carries a known stamp; an unstamped copy is preserved with a warning — delete that file manually.\n- **File replaced on `/reload`**: it kept a known stamp and was refreshed; remove the stamp to take ownership.\n- **\"No changes to review\"**: stage changes or pass `--base`.\n- **PR target fails**: needs authed `gh`; the reviewer reports that plainly (stderr verbatim on failure).\n- **Large diffs**: use a model with a bigger context window; reviewers also read files as they work.\n- **Not a git repo**: the template needs `git` on `PATH` inside a repository.\n\n## Contributing\n\nThis package lives in the `opencode-plugins` monorepo. Run `bun run build`, `bun run typecheck`, `bun run lint`, and `bun test` before opening a PR. Please check for existing issues first.\n\n## License\n\n[MPL-2.0](./LICENSE.txt)\n","readmeFilename":"README.md"}