@capybearista/opencode-adversarial-review 1.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +94 -88
- package/commands/adversarial-review.md +28 -0
- package/commands/constructive-review.md +30 -0
- package/dist/index.d.ts +6 -6
- package/dist/index.js +423 -169
- package/dist/index.js.map +1 -1
- package/dist/prompt.d.ts +6 -0
- package/dist/prompt.js +221 -0
- package/dist/prompt.js.map +1 -0
- package/package.json +12 -9
- package/server.js +1 -0
- /package/{LICENSE → LICENSE.txt} +0 -0
package/README.md
CHANGED
|
@@ -1,161 +1,167 @@
|
|
|
1
1
|
# opencode-adversarial-review
|
|
2
2
|
|
|
3
|
-
<p align="center">
|
|
3
|
+
<p align="center">Unbiased challenges and reviews for your code</p>
|
|
4
4
|
<p align="center">
|
|
5
|
-
<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>
|
|
6
|
-
<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>
|
|
7
|
-
<a href="https://opencode.ai"><img alt="opencode" src="https://img.shields.io/badge/OpenCode-Plugin-orange?style=flat-square&color=60a5e6
|
|
8
|
-
" /></a>
|
|
5
|
+
<a href="https://www.npmjs.com/package/@capybearista/opencode-adversarial-review"><img alt="npm version" src="https://img.shields.io/npm/v/@capybearista/opencode-adversarial-review?style=flat-square&color=8d60e6" /></a>
|
|
6
|
+
<a href="https://www.npmjs.com/package/@capybearista/opencode-adversarial-review"><img alt="npm downloads" src="https://img.shields.io/npm/dm/@capybearista/opencode-adversarial-review?style=flat-square&color=6067e6" /></a>
|
|
7
|
+
<a href="https://opencode.ai"><img alt="opencode" src="https://img.shields.io/badge/OpenCode-Plugin-orange?style=flat-square&color=60a5e6" /></a>
|
|
9
8
|
<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>
|
|
10
9
|
</p>
|
|
10
|
+
|
|
11
11
|
---
|
|
12
12
|
|
|
13
13
|
## Why?
|
|
14
14
|
|
|
15
|
-
>
|
|
15
|
+
> Two 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 general **constructive reviewer** that checks correctness first and suggests improvements.
|
|
16
16
|
|
|
17
17
|
## Philosophy: Extending OpenCode
|
|
18
18
|
|
|
19
|
-
OpenCode is designed to be highly extensible. This plugin
|
|
19
|
+
OpenCode is designed to be highly extensible. This plugin adds adversarial and constructive review passes directly to your workflow.
|
|
20
20
|
|
|
21
21
|
### Architecture
|
|
22
22
|
|
|
23
23
|
```mermaid
|
|
24
24
|
graph TB
|
|
25
|
-
subgraph
|
|
26
|
-
User([User])
|
|
25
|
+
subgraph OpenCode [OpenCode]
|
|
26
|
+
User([User]) -->|"/adversarial-review / /constructive-review"| Command[Installed Command Templates]
|
|
27
|
+
Command -->|"$ARGUMENTS + five shell blocks"| Reviewer
|
|
27
28
|
end
|
|
28
29
|
|
|
29
|
-
subgraph
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
Command -->|!git log| L[Commits]
|
|
33
|
-
Command -->|!git diff| D[Diff Summary]
|
|
34
|
-
Command -->|!cat| U[Untracked]
|
|
30
|
+
subgraph Plugin [Plugin]
|
|
31
|
+
Setup[setup] -->|registers| Reviewer{"adversarial-reviewer<br/>constructive-reviewer<br/>hidden subagents"}
|
|
32
|
+
Setup -->|"atomic install; stamped refresh"| Command
|
|
35
33
|
end
|
|
36
34
|
|
|
37
|
-
subgraph
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
Reviewer -->|Self-Collect| Tools[Explorer Tools]
|
|
43
|
-
Tools -->|Source Code| Reviewer
|
|
35
|
+
subgraph Review [Review Session]
|
|
36
|
+
Reviewer -->|self-collected evidence| Tools[read / grep / glob / git / gh]
|
|
37
|
+
Tools --> Reviewer
|
|
38
|
+
Reviewer -->|"requested output: JSON / Markdown"| User
|
|
44
39
|
end
|
|
45
40
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
classDef host fill:#bbf,stroke:#333,stroke-width:2px;
|
|
49
|
-
classDef collection fill:#dfd,stroke:#333,stroke-width:1px,stroke-dasharray: 5 5;
|
|
41
|
+
classDef opencode fill:#bbf,stroke:#333,stroke-width:2px;
|
|
42
|
+
classDef plugin fill:#dfd,stroke:#333,stroke-width:1px,stroke-dasharray: 5 5;
|
|
50
43
|
classDef adversary fill:#f9f,stroke:#333,stroke-width:2px;
|
|
51
|
-
|
|
52
|
-
class
|
|
53
|
-
class
|
|
54
|
-
class
|
|
44
|
+
|
|
45
|
+
class OpenCode opencode;
|
|
46
|
+
class Plugin plugin;
|
|
47
|
+
class Review adversary;
|
|
55
48
|
```
|
|
56
49
|
|
|
57
|
-
|
|
50
|
+
One config drives two sandboxed subagents: agents register in memory and commands install to disk,
|
|
51
|
+
|
|
52
|
+
- **Agents**: setup registers the hidden `adversarial-reviewer` and `constructive-reviewer` subagents; nothing is written to your agents directory.
|
|
53
|
+
- **Commands**: setup installs `~/.config/opencode/commands/adversarial-review.md` and `~/.config/opencode/commands/constructive-review.md` into your OpenCode config directory.
|
|
54
|
+
- **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.
|
|
58
55
|
|
|
59
56
|
## Features
|
|
60
57
|
|
|
61
|
-
- **
|
|
62
|
-
- **
|
|
63
|
-
- **
|
|
64
|
-
- **
|
|
65
|
-
- **Configurable Scope**: Support for `--base <ref>`, `--scope branch`, and `--scope working-tree`.
|
|
58
|
+
- **Two reviewers**: adversarial (reasons *not* to ship) and constructive (correctness first, then suggestions).
|
|
59
|
+
- **Reviewer-collected evidence**: changed files, untracked files, and branch diffs are inspected with read-only tools; only verified findings are reported.
|
|
60
|
+
- **Auto-installed commands**: both slash commands are written on first setup; stamped files refresh on `/reload`, user-owned edits are preserved (see note below).
|
|
61
|
+
- **Targets**: `--scope`, `--base`, bare commit SHA, or PR URL/number on both commands.
|
|
66
62
|
|
|
67
63
|
## Install
|
|
68
64
|
|
|
69
|
-
|
|
65
|
+
### OpenCode V2
|
|
66
|
+
|
|
67
|
+
Add it under the `"plugins"` key in `opencode.json(c)`:
|
|
68
|
+
|
|
70
69
|
```json
|
|
71
70
|
{
|
|
72
|
-
"
|
|
71
|
+
"plugins": ["@capybearista/opencode-adversarial-review@latest"]
|
|
73
72
|
}
|
|
74
73
|
```
|
|
75
74
|
|
|
76
|
-
|
|
75
|
+
Server entry only, so `cli.json` needs no entry.
|
|
77
76
|
|
|
78
|
-
|
|
79
|
-
opencode plugin -g @capybearista/opencode-adversarial-review # global install
|
|
80
|
-
opencode plugin @capybearista/opencode-adversarial-review # project-local install
|
|
81
|
-
```
|
|
77
|
+
### OpenCode V1
|
|
82
78
|
|
|
83
|
-
|
|
79
|
+
Add it under the `"plugin"` key in `opencode.json(c)`:
|
|
84
80
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
/adversarial-review
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"plugin": ["@capybearista/opencode-adversarial-review@1.0.0"]
|
|
84
|
+
}
|
|
88
85
|
```
|
|
89
86
|
|
|
90
|
-
|
|
87
|
+
Server entry only, so `tui.json(c)` needs no entry.
|
|
91
88
|
|
|
92
|
-
|
|
93
|
-
| :--- | :--- | :--- |
|
|
94
|
-
| `--scope` | `auto`, `working-tree`, `branch` | The range of changes to review. Defaults to `auto`. |
|
|
95
|
-
| `--base` | `<git-ref>` | The base reference (branch or commit) to compare against when using `branch` scope. |
|
|
89
|
+
See the [V1 plugin guide](../../docs/v1-plugins.md) for details.
|
|
96
90
|
|
|
97
|
-
-
|
|
98
|
-
- **`working-tree`**: Reviews staged and unstaged changes against `HEAD`.
|
|
99
|
-
- **`branch`**: Reviews all changes on the current branch since it diverged from the upstream or main branch.
|
|
100
|
-
- **`focus ...`**: Any trailing text is treated as a focus area for the review.
|
|
91
|
+
On setup, both command files install at `~/.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.
|
|
101
92
|
|
|
102
|
-
###
|
|
93
|
+
### Uninstall
|
|
103
94
|
|
|
104
|
-
|
|
105
|
-
```bash
|
|
106
|
-
/adversarial-review --scope working-tree
|
|
107
|
-
```
|
|
95
|
+
Remove the plugin from `"plugin(s)"` from the respective config files they were added to. Then delete both installed command files—plugin removal does not delete them, and OpenCode would otherwise keep discovering commands with no agents behind them.
|
|
108
96
|
|
|
109
|
-
|
|
110
|
-
```bash
|
|
111
|
-
/adversarial-review --scope branch
|
|
112
|
-
```
|
|
97
|
+
## Usage
|
|
113
98
|
|
|
114
|
-
|
|
115
|
-
```bash
|
|
116
|
-
/adversarial-review --base main
|
|
117
|
-
```
|
|
99
|
+
Both 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).
|
|
118
100
|
|
|
119
|
-
Review with a specific focus area:
|
|
120
101
|
```bash
|
|
121
|
-
/adversarial-review
|
|
102
|
+
/adversarial-review # working tree (or branch, if tree is clean)
|
|
103
|
+
/adversarial-review --scope branch # current branch since fork point
|
|
104
|
+
/adversarial-review 4f2a9c1e # a commit
|
|
105
|
+
/adversarial-review 42 # PR #42 (bare number; hex SHAs stay commits)
|
|
106
|
+
/constructive-review --scope working-tree # constructive pass, working tree only
|
|
107
|
+
/constructive-review --scope branch # constructive pass, current branch since fork point
|
|
108
|
+
/constructive-review 4f2a9c1e # constructive pass, a commit
|
|
109
|
+
/constructive-review 42 # constructive pass, PR #42
|
|
122
110
|
```
|
|
123
111
|
|
|
112
|
+
> [!NOTE]
|
|
113
|
+
> 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.
|
|
114
|
+
>
|
|
115
|
+
> 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 OpenCode 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.
|
|
116
|
+
|
|
124
117
|
## Configuration
|
|
125
118
|
|
|
126
|
-
|
|
127
|
-
| :--- | :--- | :--- |
|
|
128
|
-
| `agent.adversarial-review.model` | `string` | The model to use for the subagent (defaults to `openai/gpt-5.4`). |
|
|
129
|
-
| `agent.adversarial-review.temperature` | `number` | Sampling temperature (defaults to `0.1` for deterministic review). |
|
|
130
|
-
| `command.adversarial-review.template` | `string` | The shell-injected template used to gather git context. |
|
|
119
|
+
Nothing 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`:
|
|
131
120
|
|
|
132
|
-
|
|
121
|
+
```jsonc
|
|
122
|
+
{
|
|
123
|
+
"agents": {
|
|
124
|
+
"adversarial-reviewer": { "model": "openrouter/openai/gpt-6-sol" },
|
|
125
|
+
"constructive-reviewer": { "model": "openrouter/openai/gpt-6-sol" }
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
```
|
|
133
129
|
|
|
134
130
|
## Permissions & Security
|
|
135
131
|
|
|
136
|
-
|
|
132
|
+
Both reviewers are sandboxed and unattended; the single accepted risk is pasted arguments (below). Details:
|
|
133
|
+
|
|
134
|
+
**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.
|
|
137
135
|
|
|
138
|
-
-
|
|
139
|
-
- **Bash**: Restricted to a read-only whitelist of 12 Git patterns (e.g., `git diff`, `git log`, `git status`). All other shell commands are blocked.
|
|
140
|
-
- **Read/Grep/Glob**: Allowed (read-only) to enable code inspection.
|
|
141
|
-
- **Network**: Web fetch and search are disabled to ensure the review remains focused on the files at hand.
|
|
136
|
+
One 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.
|
|
142
137
|
|
|
143
138
|
## Troubleshooting
|
|
144
139
|
|
|
145
|
-
- **
|
|
146
|
-
- **
|
|
147
|
-
- **
|
|
140
|
+
- **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.
|
|
141
|
+
- **"Leaving it untouched" warning**: the file is user-owned or carries an unknown/newer stamp — edit in place, or delete to reinstall.
|
|
142
|
+
- **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.
|
|
143
|
+
- **File replaced on `/reload`**: it kept a known stamp and was refreshed; remove the stamp to take ownership.
|
|
144
|
+
- **"No changes to review"**: stage changes or pass `--base`.
|
|
145
|
+
- **PR target fails**: needs authed `gh`; the reviewer reports that plainly (stderr verbatim on failure).
|
|
146
|
+
- **Large diffs**: use a model with a bigger context window; reviewers also read files as they work.
|
|
147
|
+
- **Not a git repo**: the template needs `git` on `PATH` inside a repository.
|
|
148
148
|
|
|
149
149
|
## Contributing
|
|
150
150
|
|
|
151
151
|
This package lives in the `opencode-plugins` monorepo.
|
|
152
152
|
|
|
153
|
-
|
|
154
|
-
|
|
153
|
+
See the [contribution guidelines](../../CONTRIBUTING.md) before opening a pull request.
|
|
154
|
+
|
|
155
|
+
- From the monorepo root, run `bun run build` before artifact checks, then `bun run typecheck`,
|
|
156
|
+
`bun run lint`, and the canonical `bun run test` Turbo pipeline. Do not use bare root `bun test`
|
|
157
|
+
as the workspace check.
|
|
158
|
+
- For a focused run, `bun test` is supported from this package directory; its tests include the
|
|
159
|
+
real local-directory resolver regression.
|
|
160
|
+
- `bun run check` writes Biome changes; use it only when formatting changes are intended.
|
|
155
161
|
- Prefer small, direct changes.
|
|
156
162
|
|
|
157
163
|
Please open an issue or check for existing ones before creating a pull request.
|
|
158
164
|
|
|
159
165
|
## License
|
|
160
166
|
|
|
161
|
-
[MPL-2.0](LICENSE)
|
|
167
|
+
[MPL-2.0](./LICENSE.txt)
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Adversarial code review: challenges the implementation. Args: [<sha|pr-url|pr-number>] [--base <ref>] [--scope auto|working-tree|branch] [focus ...]"
|
|
3
|
+
agent: adversarial-reviewer
|
|
4
|
+
subagent: true
|
|
5
|
+
managed_version: 2
|
|
6
|
+
metadata: Managed by @capybearista/opencode-adversarial-review. Keep the managed_version stamp to receive bundled-template updates on /reload or restart; remove it to take ownership and your version is then preserved with a warning; a stamp newer than the shipped template is also preserved.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Adversarial review handoff
|
|
10
|
+
|
|
11
|
+
You are the adversarial reviewer for this repository. Review the change and return the structured JSON verdict defined in your system prompt.
|
|
12
|
+
|
|
13
|
+
Target selection, focus weighting, evidence rules, and the output contract live in your system prompt — follow them.
|
|
14
|
+
|
|
15
|
+
Args and focus: $ARGUMENTS
|
|
16
|
+
|
|
17
|
+
The blocks below are a point-in-time snapshot rendered by this template. They can be incomplete: commands can fail, output can be empty, and untracked file contents are not inlined. Verify everything with your own read-only tools before reporting.
|
|
18
|
+
|
|
19
|
+
- Branch:
|
|
20
|
+
!`git branch --show-current 2>&1 || true`
|
|
21
|
+
- Status:
|
|
22
|
+
!`git status --short --untracked-files=all 2>&1 || true`
|
|
23
|
+
- Recent commits:
|
|
24
|
+
!`git log --oneline -3 2>&1 || true`
|
|
25
|
+
- Working-tree diff against HEAD:
|
|
26
|
+
!`git diff HEAD 2>&1 || true`
|
|
27
|
+
- Untracked files (paths only; read their contents with your tools):
|
|
28
|
+
!`git ls-files --others --exclude-standard 2>&1 || true`
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Constructive code review: correctness and risk. Args: [<sha|pr-url|pr-number>] [--base <ref>] [--scope auto|working-tree|branch]"
|
|
3
|
+
agent: constructive-reviewer
|
|
4
|
+
subagent: true
|
|
5
|
+
managed_version: 2
|
|
6
|
+
metadata: Managed by @capybearista/opencode-adversarial-review. Keep the managed_version stamp to receive bundled-template updates on /reload or restart; remove it to take ownership and your version is then preserved with a warning; a stamp newer than the shipped template is also preserved.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Review handoff
|
|
10
|
+
|
|
11
|
+
You are the constructive reviewer for this repository. Review the change for correctness first, then for material maintainability risk, and return the Markdown report defined in your system prompt.
|
|
12
|
+
|
|
13
|
+
Review only: do not modify the repository; report findings and suggestions for the author to apply.
|
|
14
|
+
|
|
15
|
+
Target selection (scope flags and explicit targets; no focus text), evidence rules, and the output contract live in your system prompt — follow them.
|
|
16
|
+
|
|
17
|
+
Args: $ARGUMENTS
|
|
18
|
+
|
|
19
|
+
The blocks below are a point-in-time snapshot rendered by this template. They can be incomplete: commands can fail, output can be empty, and untracked file contents are not inlined. Verify everything with your own read-only tools before reporting.
|
|
20
|
+
|
|
21
|
+
- Branch:
|
|
22
|
+
!`git branch --show-current 2>&1 || true`
|
|
23
|
+
- Status:
|
|
24
|
+
!`git status --short --untracked-files=all 2>&1 || true`
|
|
25
|
+
- Recent commits:
|
|
26
|
+
!`git log --oneline -3 2>&1 || true`
|
|
27
|
+
- Working-tree diff against HEAD:
|
|
28
|
+
!`git diff HEAD 2>&1 || true`
|
|
29
|
+
- Untracked files (paths only; read their contents with your tools):
|
|
30
|
+
!`git ls-files --others --exclude-standard 2>&1 || true`
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
export declare const
|
|
3
|
-
declare const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { Plugin } from "@opencode/plugin";
|
|
2
|
+
export declare const CURRENT_TEMPLATE_VERSION = 2;
|
|
3
|
+
export declare const KNOWN_TEMPLATE_VERSIONS: readonly number[];
|
|
4
|
+
export declare function managedVersionOf(markdown: string): number | undefined;
|
|
5
|
+
export declare function isManagedUpgrade(installedVersion: number, knownVersions: readonly number[], currentVersion: number): boolean;
|
|
6
|
+
declare const _default: Plugin.Plugin;
|
|
7
7
|
export default _default;
|