@mechanai/deepreview 2.1.2 → 2.1.4
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.
|
@@ -18,16 +18,55 @@ Check if input.txt is empty (0 bytes). If empty, tell the user "Nothing to revie
|
|
|
18
18
|
Get and store the PR head SHA:
|
|
19
19
|
Run `gh pr view $ARGUMENTS --json headRefOid --jq .headRefOid` and save the output as PR_HEAD_SHA.
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
STEP 3: DISPATCH STAGE 1 — INITIAL REVIEW (5 parallel tasks)
|
|
22
|
+
Dispatch ALL FIVE of these Task tool calls simultaneously in a single message:
|
|
22
23
|
|
|
23
|
-
|
|
24
|
+
Task 1 — Use the Task tool with subagent_type="deepreview-correctness":
|
|
25
|
+
"You are reviewing a PR diff (code changes). Read the content at $SESSION_DIR/input.txt. Write your review to $SESSION_DIR/review-correctness.md."
|
|
24
26
|
|
|
25
|
-
-
|
|
26
|
-
|
|
27
|
+
Task 2 — Use the Task tool with subagent_type="deepreview-security":
|
|
28
|
+
"You are reviewing a PR diff (code changes). Read the content at $SESSION_DIR/input.txt. Write your review to $SESSION_DIR/review-security.md."
|
|
29
|
+
|
|
30
|
+
Task 3 — Use the Task tool with subagent_type="deepreview-architecture":
|
|
31
|
+
"You are reviewing a PR diff (code changes). Read the content at $SESSION_DIR/input.txt. Write your review to $SESSION_DIR/review-architecture.md."
|
|
32
|
+
|
|
33
|
+
Task 4 — Use the Task tool with subagent_type="deepreview-docs":
|
|
34
|
+
"You are reviewing a PR diff (code changes). Read the content at $SESSION_DIR/input.txt. Write your review to $SESSION_DIR/review-docs.md."
|
|
35
|
+
|
|
36
|
+
Task 5 — Use the Task tool with subagent_type="deepreview-compatibility":
|
|
37
|
+
"You are reviewing a PR diff (code changes). Read the content at $SESSION_DIR/input.txt. Write your review to $SESSION_DIR/review-compatibility.md."
|
|
38
|
+
|
|
39
|
+
Wait for all 5 to return. Record which succeeded and which failed.
|
|
40
|
+
|
|
41
|
+
STEP 4: DISPATCH STAGE 2 — CROSS-VALIDATION (5 parallel tasks)
|
|
42
|
+
Only proceed with reviews that exist. Dispatch ALL FIVE simultaneously:
|
|
43
|
+
|
|
44
|
+
Task 6 — Use the Task tool with subagent_type="deepreview-validator":
|
|
45
|
+
"Your perspective: correctness. Read all review files at: $SESSION_DIR/review-correctness.md, $SESSION_DIR/review-security.md, $SESSION_DIR/review-architecture.md, $SESSION_DIR/review-docs.md, $SESSION_DIR/review-compatibility.md. Also read the original input at $SESSION_DIR/input.txt for context. Write your validated review to $SESSION_DIR/validated-correctness.md."
|
|
46
|
+
|
|
47
|
+
Task 7 — Use the Task tool with subagent_type="deepreview-validator":
|
|
48
|
+
"Your perspective: security. Read all review files at: $SESSION_DIR/review-correctness.md, $SESSION_DIR/review-security.md, $SESSION_DIR/review-architecture.md, $SESSION_DIR/review-docs.md, $SESSION_DIR/review-compatibility.md. Also read the original input at $SESSION_DIR/input.txt for context. Write your validated review to $SESSION_DIR/validated-security.md."
|
|
49
|
+
|
|
50
|
+
Task 8 — Use the Task tool with subagent_type="deepreview-validator":
|
|
51
|
+
"Your perspective: architecture. Read all review files at: $SESSION_DIR/review-correctness.md, $SESSION_DIR/review-security.md, $SESSION_DIR/review-architecture.md, $SESSION_DIR/review-docs.md, $SESSION_DIR/review-compatibility.md. Also read the original input at $SESSION_DIR/input.txt for context. Write your validated review to $SESSION_DIR/validated-architecture.md."
|
|
52
|
+
|
|
53
|
+
Task 9 — Use the Task tool with subagent_type="deepreview-validator":
|
|
54
|
+
"Your perspective: docs. Read all review files at: $SESSION_DIR/review-correctness.md, $SESSION_DIR/review-security.md, $SESSION_DIR/review-architecture.md, $SESSION_DIR/review-docs.md, $SESSION_DIR/review-compatibility.md. Also read the original input at $SESSION_DIR/input.txt for context. Write your validated review to $SESSION_DIR/validated-docs.md."
|
|
55
|
+
|
|
56
|
+
Task 10 — Use the Task tool with subagent_type="deepreview-validator":
|
|
57
|
+
"Your perspective: compatibility. Read all review files at: $SESSION_DIR/review-correctness.md, $SESSION_DIR/review-security.md, $SESSION_DIR/review-architecture.md, $SESSION_DIR/review-docs.md, $SESSION_DIR/review-compatibility.md. Also read the original input at $SESSION_DIR/input.txt for context. Write your validated review to $SESSION_DIR/validated-compatibility.md."
|
|
58
|
+
|
|
59
|
+
Wait for all 5 to return.
|
|
60
|
+
|
|
61
|
+
STEP 5: DISPATCH STAGE 3 — SYNTHESIS (1 task)
|
|
62
|
+
Task 11 — Use the Task tool with subagent_type="deepreview-synthesizer":
|
|
63
|
+
"Read the validated reviews at: $SESSION_DIR/validated-correctness.md, $SESSION_DIR/validated-security.md, $SESSION_DIR/validated-architecture.md, $SESSION_DIR/validated-docs.md, $SESSION_DIR/validated-compatibility.md (skip any that don't exist). Write the synthesis to $SESSION_DIR/synthesis.md."
|
|
64
|
+
|
|
65
|
+
Record the stats line from its return.
|
|
27
66
|
|
|
28
67
|
If stats show 0 critical, 0 warnings, 0 suggestions, tell the user "No findings to post. PR looks good!" and STOP.
|
|
29
68
|
|
|
30
|
-
STEP
|
|
69
|
+
STEP 6: FORMAT THREADS (1 task)
|
|
31
70
|
|
|
32
71
|
Get the repo owner/name:
|
|
33
72
|
Run `gh repo view --json owner,name --jq '.owner.login + "/" + .name'` and save as OWNER_REPO.
|
|
@@ -37,18 +76,18 @@ Task — Use the Task tool with subagent_type="deepreview-review-formatter":
|
|
|
37
76
|
|
|
38
77
|
Wait for it to return.
|
|
39
78
|
|
|
40
|
-
STEP
|
|
79
|
+
STEP 7: POST REVIEW
|
|
41
80
|
Use the `deepreview-post-review` tool:
|
|
42
81
|
|
|
43
82
|
- `threads_path`: The absolute path to `$SESSION_DIR/threads.md`
|
|
44
83
|
- `pr_number`: $ARGUMENTS (the PR number)
|
|
45
84
|
|
|
46
|
-
STEP
|
|
85
|
+
STEP 8: PRESENT RESULTS
|
|
47
86
|
Show the user:
|
|
48
87
|
|
|
49
88
|
- Session directory: $SESSION_DIR/
|
|
50
89
|
- Which reviewers completed (and any that failed)
|
|
51
|
-
- Stats from synthesis (the stats line from
|
|
90
|
+
- Stats from synthesis (the stats line from Step 5)
|
|
52
91
|
- Output from the posting script (how many threads posted, any demotions)
|
|
53
92
|
- Remind: "The review is PENDING. Submit it via the GitHub UI when ready."
|
|
54
93
|
|
package/dist/setup.mjs
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/setup.ts
|
|
4
|
+
import {
|
|
5
|
+
existsSync,
|
|
6
|
+
lstatSync,
|
|
7
|
+
mkdirSync,
|
|
8
|
+
readdirSync,
|
|
9
|
+
symlinkSync,
|
|
10
|
+
unlinkSync,
|
|
11
|
+
readFileSync,
|
|
12
|
+
writeFileSync
|
|
13
|
+
} from "node:fs";
|
|
14
|
+
import path from "node:path";
|
|
15
|
+
import os from "node:os";
|
|
16
|
+
import { applyEdits, modify, parse as parseJsonc } from "jsonc-parser";
|
|
17
|
+
var PACKAGE_NAME = "@mechanai/deepreview";
|
|
18
|
+
var local = process.argv.includes("--local");
|
|
19
|
+
var cwd = process.cwd();
|
|
20
|
+
var globalConfigDir = path.join(process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), ".config"), "opencode");
|
|
21
|
+
var targetDir = local ? path.join(cwd, ".opencode") : globalConfigDir;
|
|
22
|
+
var packageDir = path.resolve(import.meta.dirname, "..");
|
|
23
|
+
var packageOpencode = path.join(packageDir, ".opencode");
|
|
24
|
+
function ensurePluginInConfig() {
|
|
25
|
+
const configFiles = ["opencode.jsonc", "opencode.json"];
|
|
26
|
+
const searchDir = local ? cwd : globalConfigDir;
|
|
27
|
+
let configPath;
|
|
28
|
+
for (const file of configFiles) {
|
|
29
|
+
const candidate = path.join(searchDir, file);
|
|
30
|
+
if (existsSync(candidate)) {
|
|
31
|
+
configPath = candidate;
|
|
32
|
+
break;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (configPath === undefined) {
|
|
36
|
+
configPath = path.join(searchDir, "opencode.json");
|
|
37
|
+
mkdirSync(searchDir, { recursive: true });
|
|
38
|
+
writeFileSync(configPath, JSON.stringify({ plugin: [PACKAGE_NAME] }, null, 2) + `
|
|
39
|
+
`);
|
|
40
|
+
console.log(`Created ${configPath} with plugin entry.`);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const raw = readFileSync(configPath, "utf-8");
|
|
44
|
+
let config;
|
|
45
|
+
try {
|
|
46
|
+
const parsed = parseJsonc(raw);
|
|
47
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
48
|
+
throw new Error("not an object");
|
|
49
|
+
}
|
|
50
|
+
config = parsed;
|
|
51
|
+
} catch {
|
|
52
|
+
console.error(`Could not parse ${configPath}. Add the plugin manually:`);
|
|
53
|
+
console.error(` "plugin": ["${PACKAGE_NAME}"]`);
|
|
54
|
+
process.exitCode = 1;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const pluginArray = Array.isArray(config.plugin) ? config.plugin : [];
|
|
58
|
+
const plugins = pluginArray.filter((p) => typeof p === "string");
|
|
59
|
+
if (plugins.includes(PACKAGE_NAME)) {
|
|
60
|
+
console.log(`Plugin already registered in ${configPath}.`);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const formatting = { formattingOptions: { insertSpaces: true, tabSize: 2 } };
|
|
64
|
+
const edits = Array.isArray(config.plugin) ? modify(raw, ["plugin", pluginArray.length], PACKAGE_NAME, formatting) : modify(raw, ["plugin"], [PACKAGE_NAME], formatting);
|
|
65
|
+
writeFileSync(configPath, applyEdits(raw, edits));
|
|
66
|
+
console.log(`Added "${PACKAGE_NAME}" to plugin array in ${configPath}.`);
|
|
67
|
+
}
|
|
68
|
+
function symlinkDirectory(kind) {
|
|
69
|
+
const sourceDir = path.join(packageOpencode, kind);
|
|
70
|
+
if (!existsSync(sourceDir))
|
|
71
|
+
return;
|
|
72
|
+
const destDir = path.join(targetDir, kind);
|
|
73
|
+
mkdirSync(destDir, { recursive: true });
|
|
74
|
+
const sourceFiles = new Set(readdirSync(sourceDir).filter((f) => f.endsWith(".md")));
|
|
75
|
+
let created = 0;
|
|
76
|
+
for (const file of readdirSync(destDir)) {
|
|
77
|
+
if (!file.startsWith("deepreview-") && !file.startsWith("_deepreview-"))
|
|
78
|
+
continue;
|
|
79
|
+
const dest = path.join(destDir, file);
|
|
80
|
+
try {
|
|
81
|
+
if (lstatSync(dest).isSymbolicLink() && !sourceFiles.has(file)) {
|
|
82
|
+
unlinkSync(dest);
|
|
83
|
+
}
|
|
84
|
+
} catch (err) {
|
|
85
|
+
if (err instanceof Error && !(("code" in err) && err.code === "ENOENT")) {
|
|
86
|
+
console.warn(`Could not check ${dest}: ${err.message}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
for (const file of sourceFiles) {
|
|
91
|
+
const dest = path.join(destDir, file);
|
|
92
|
+
const source = path.relative(destDir, path.join(sourceDir, file));
|
|
93
|
+
try {
|
|
94
|
+
const stat = lstatSync(dest);
|
|
95
|
+
if (!stat.isSymbolicLink()) {
|
|
96
|
+
console.warn(`Skipping ${dest}: not a symlink (would overwrite regular file)`);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
unlinkSync(dest);
|
|
100
|
+
} catch (err) {
|
|
101
|
+
if (err instanceof Error && "code" in err && err.code !== "ENOENT") {
|
|
102
|
+
throw err;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
symlinkSync(source, dest);
|
|
106
|
+
created++;
|
|
107
|
+
}
|
|
108
|
+
const label = local ? `.opencode/${kind}/` : path.join(targetDir, kind) + "/";
|
|
109
|
+
console.log(`Linked ${created} ${kind} into ${label}`);
|
|
110
|
+
}
|
|
111
|
+
ensurePluginInConfig();
|
|
112
|
+
symlinkDirectory("agents");
|
|
113
|
+
symlinkDirectory("commands");
|
|
114
|
+
var scope = local ? "project" : "global";
|
|
115
|
+
console.log(`Done (${scope}). Run opencode to use /deepreview commands.`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mechanai/deepreview",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.4",
|
|
4
4
|
"description": "Multi-agent parallel code/spec review for OpenCode",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -25,6 +25,9 @@
|
|
|
25
25
|
"publishConfig": {
|
|
26
26
|
"access": "public"
|
|
27
27
|
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"prepare": "mise run build"
|
|
30
|
+
},
|
|
28
31
|
"dependencies": {
|
|
29
32
|
"gray-matter": "4.0.3",
|
|
30
33
|
"js-yaml": "4.1.0",
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
internal: true
|
|
3
|
-
description: "Shared pipeline stages for deepreview commands (review → validate → synthesize)"
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Shared Pipeline: Review → Validate → Synthesize
|
|
7
|
-
|
|
8
|
-
This template defines 3 stages used by deepreview orchestrator commands. The orchestrator must set SESSION_DIR and INPUT_DESCRIPTION before invoking these stages.
|
|
9
|
-
|
|
10
|
-
## STAGE 1: INITIAL REVIEW (one task per review perspective)
|
|
11
|
-
|
|
12
|
-
Dispatch ALL of these Task tool calls simultaneously in a single message:
|
|
13
|
-
|
|
14
|
-
Task — Use the Task tool with subagent_type="deepreview-correctness":
|
|
15
|
-
"You are reviewing $INPUT_DESCRIPTION. Read the content at $SESSION_DIR/input.txt. Write your review to $SESSION_DIR/review-correctness.md."
|
|
16
|
-
|
|
17
|
-
Task — Use the Task tool with subagent_type="deepreview-security":
|
|
18
|
-
"You are reviewing $INPUT_DESCRIPTION. Read the content at $SESSION_DIR/input.txt. Write your review to $SESSION_DIR/review-security.md."
|
|
19
|
-
|
|
20
|
-
Task — Use the Task tool with subagent_type="deepreview-architecture":
|
|
21
|
-
"You are reviewing $INPUT_DESCRIPTION. Read the content at $SESSION_DIR/input.txt. Write your review to $SESSION_DIR/review-architecture.md."
|
|
22
|
-
|
|
23
|
-
Task — Use the Task tool with subagent_type="deepreview-docs":
|
|
24
|
-
"You are reviewing $INPUT_DESCRIPTION. Read the content at $SESSION_DIR/input.txt. Write your review to $SESSION_DIR/review-docs.md."
|
|
25
|
-
|
|
26
|
-
Task — Use the Task tool with subagent_type="deepreview-compatibility":
|
|
27
|
-
"You are reviewing $INPUT_DESCRIPTION. Read the content at $SESSION_DIR/input.txt. Write your review to $SESSION_DIR/review-compatibility.md."
|
|
28
|
-
|
|
29
|
-
Wait for all 5 to return. Record which succeeded and which failed.
|
|
30
|
-
|
|
31
|
-
## STAGE 2: CROSS-VALIDATION (5 parallel tasks)
|
|
32
|
-
|
|
33
|
-
Only proceed with reviews that exist. For each validator below, replace $REVIEW_FILE_LIST with ONLY the review files that were successfully created in Stage 1. If a review file failed, omit it from the list entirely. Dispatch validators simultaneously:
|
|
34
|
-
|
|
35
|
-
Task — Use the Task tool with subagent_type="deepreview-validator":
|
|
36
|
-
"Your perspective: correctness. Read all available review files at: $REVIEW_FILE_LIST. Also read the original input at $SESSION_DIR/input.txt for context. Write your validated review to $SESSION_DIR/validated-correctness.md."
|
|
37
|
-
|
|
38
|
-
Task — Use the Task tool with subagent_type="deepreview-validator":
|
|
39
|
-
"Your perspective: security. Read all available review files at: $REVIEW_FILE_LIST. Also read the original input at $SESSION_DIR/input.txt for context. Write your validated review to $SESSION_DIR/validated-security.md."
|
|
40
|
-
|
|
41
|
-
Task — Use the Task tool with subagent_type="deepreview-validator":
|
|
42
|
-
"Your perspective: architecture. Read all available review files at: $REVIEW_FILE_LIST. Also read the original input at $SESSION_DIR/input.txt for context. Write your validated review to $SESSION_DIR/validated-architecture.md."
|
|
43
|
-
|
|
44
|
-
Task — Use the Task tool with subagent_type="deepreview-validator":
|
|
45
|
-
"Your perspective: docs. Read all available review files at: $REVIEW_FILE_LIST. Also read the original input at $SESSION_DIR/input.txt for context. Write your validated review to $SESSION_DIR/validated-docs.md."
|
|
46
|
-
|
|
47
|
-
Task — Use the Task tool with subagent_type="deepreview-validator":
|
|
48
|
-
"Your perspective: compatibility. Read all available review files at: $REVIEW_FILE_LIST. Also read the original input at $SESSION_DIR/input.txt for context. Write your validated review to $SESSION_DIR/validated-compatibility.md."
|
|
49
|
-
|
|
50
|
-
Wait for all 5 to return.
|
|
51
|
-
|
|
52
|
-
## STAGE 3: SYNTHESIS (1 task)
|
|
53
|
-
|
|
54
|
-
Task — Use the Task tool with subagent_type="deepreview-synthesizer":
|
|
55
|
-
"Read the validated reviews at: $SESSION_DIR/validated-correctness.md, $SESSION_DIR/validated-security.md, $SESSION_DIR/validated-architecture.md, $SESSION_DIR/validated-docs.md, $SESSION_DIR/validated-compatibility.md (skip any that don't exist). Write the synthesis to $SESSION_DIR/synthesis.md."
|
|
56
|
-
|
|
57
|
-
Record the stats line from its return.
|