opencode-magi 0.10.0 → 0.11.0

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.
Files changed (126) hide show
  1. package/README.ja.md +254 -0
  2. package/README.md +31 -26
  3. package/dist/commands.js +11 -9
  4. package/dist/config/index.js +2 -0
  5. package/dist/config/resolve.js +120 -246
  6. package/dist/config/validate.js +103 -1110
  7. package/dist/constant.js +135 -0
  8. package/dist/graphql/index.generated.js +125 -0
  9. package/dist/graphql/index.js +49 -0
  10. package/dist/index.js +12 -800
  11. package/dist/magi.js +357 -0
  12. package/dist/permissions/common.json +22 -22
  13. package/dist/permissions/editor.json +12 -12
  14. package/dist/prompts/index.js +98 -0
  15. package/dist/prompts/merge/ci-classification/output-contract.md +22 -0
  16. package/dist/prompts/merge/ci-classification/task.md +10 -0
  17. package/dist/prompts/merge/ci-classification/validate.json +20 -0
  18. package/dist/prompts/merge/conflict/output-contract.md +12 -0
  19. package/dist/prompts/merge/conflict/task.md +9 -0
  20. package/dist/prompts/merge/conflict/validate.json +4 -0
  21. package/dist/prompts/merge/edit/output-contract.md +26 -0
  22. package/dist/prompts/merge/edit/task.md +10 -0
  23. package/dist/prompts/merge/edit/validate.json +60 -0
  24. package/dist/prompts/review/ci-classification/output-contract.md +21 -0
  25. package/dist/prompts/review/ci-classification/task.md +7 -0
  26. package/dist/prompts/review/ci-classification/validate.json +20 -0
  27. package/dist/prompts/review/close-reconsideration/output-contract.md +21 -0
  28. package/dist/prompts/review/close-reconsideration/task.md +6 -0
  29. package/dist/prompts/review/close-reconsideration/validate.json +44 -0
  30. package/dist/prompts/review/comment/output-contract.md +11 -0
  31. package/dist/prompts/review/comment/task.md +3 -0
  32. package/dist/prompts/review/comment/validate.json +8 -0
  33. package/dist/prompts/review/finding-validation/output-contract.md +25 -0
  34. package/dist/prompts/{templates/review/finding-validation.md → review/finding-validation/task.md} +2 -3
  35. package/dist/prompts/review/finding-validation/validate.json +21 -0
  36. package/dist/prompts/review/rereview/output-contract.md +30 -0
  37. package/dist/prompts/{templates/review/rereview.md → review/rereview/task.md} +8 -11
  38. package/dist/prompts/review/rereview/validate.json +87 -0
  39. package/dist/prompts/review/review/output-contract.md +25 -0
  40. package/dist/prompts/{templates/review/review.md → review/review/task.md} +2 -5
  41. package/dist/prompts/review/review/validate.json +54 -0
  42. package/dist/prompts/triage/acceptance/output-contract.md +16 -0
  43. package/dist/prompts/triage/acceptance/validate.json +23 -0
  44. package/dist/prompts/triage/category/output-contract.md +16 -0
  45. package/dist/prompts/triage/category/validate.json +23 -0
  46. package/dist/prompts/triage/comment-classification/output-contract.md +15 -0
  47. package/dist/prompts/triage/comment-classification/validate.json +28 -0
  48. package/dist/prompts/triage/create/output-contract.md +28 -0
  49. package/dist/prompts/triage/create/validate.json +73 -0
  50. package/dist/prompts/triage/deplicate/output-contract.md +16 -0
  51. package/dist/prompts/triage/deplicate/validate.json +20 -0
  52. package/dist/prompts/triage/existing/output-contract.md +16 -0
  53. package/dist/prompts/triage/existing/validate.json +13 -0
  54. package/dist/prompts/triage/reconsider/output-contract.md +16 -0
  55. package/dist/prompts/triage/reconsider/validate.json +23 -0
  56. package/dist/prompts/triage/signal/output-contract.md +19 -0
  57. package/dist/prompts/triage/signal/validate.json +18 -0
  58. package/dist/tools/clear/index.js +21 -0
  59. package/dist/tools/index.js +12 -0
  60. package/dist/tools/merge/action.js +47 -0
  61. package/dist/tools/merge/context.js +118 -0
  62. package/dist/tools/merge/editor.js +264 -0
  63. package/dist/tools/merge/index.js +151 -0
  64. package/dist/tools/merge/index.type.js +1 -0
  65. package/dist/tools/merge/merge.js +42 -0
  66. package/dist/tools/merge/report.js +73 -0
  67. package/dist/tools/review/action.js +429 -0
  68. package/dist/tools/review/check.js +295 -0
  69. package/dist/tools/review/context.js +258 -0
  70. package/dist/tools/review/index.js +104 -0
  71. package/dist/tools/review/index.type.js +1 -0
  72. package/dist/tools/review/report.js +143 -0
  73. package/dist/tools/review/review.js +145 -0
  74. package/dist/tools/review/reviewer.js +409 -0
  75. package/dist/tools/triage/index.js +16 -0
  76. package/dist/tools/validate/index.js +28 -0
  77. package/dist/utils/array.js +6 -0
  78. package/dist/utils/assertion.js +38 -0
  79. package/dist/utils/exec.js +14 -0
  80. package/dist/utils/fs.js +24 -0
  81. package/dist/utils/function.js +37 -0
  82. package/dist/utils/github.js +63 -0
  83. package/dist/utils/index.js +10 -0
  84. package/dist/utils/index.type.js +1 -0
  85. package/dist/utils/object.js +21 -0
  86. package/dist/utils/opencode.js +25 -0
  87. package/dist/utils/string.js +38 -0
  88. package/dist/utils/worker.js +30 -0
  89. package/package.json +20 -8
  90. package/schema.json +6 -4
  91. package/dist/config/load.js +0 -62
  92. package/dist/config/output.js +0 -25
  93. package/dist/config/worktree.js +0 -25
  94. package/dist/github/commands.js +0 -905
  95. package/dist/github/retry.js +0 -44
  96. package/dist/orchestrator/abort.js +0 -9
  97. package/dist/orchestrator/ci.js +0 -579
  98. package/dist/orchestrator/findings.js +0 -88
  99. package/dist/orchestrator/inline-comments.js +0 -73
  100. package/dist/orchestrator/majority.js +0 -62
  101. package/dist/orchestrator/merge.js +0 -1260
  102. package/dist/orchestrator/model.js +0 -216
  103. package/dist/orchestrator/pool.js +0 -15
  104. package/dist/orchestrator/report.js +0 -175
  105. package/dist/orchestrator/review-context.js +0 -342
  106. package/dist/orchestrator/review.js +0 -1480
  107. package/dist/orchestrator/run-manager.js +0 -2132
  108. package/dist/orchestrator/safety.js +0 -44
  109. package/dist/orchestrator/triage.js +0 -1370
  110. package/dist/prompts/compose.js +0 -473
  111. package/dist/prompts/contracts.js +0 -300
  112. package/dist/prompts/output.js +0 -401
  113. package/dist/prompts/templates/merge/ci-classification.md +0 -16
  114. package/dist/prompts/templates/merge/conflict.md +0 -10
  115. package/dist/prompts/templates/merge/edit.md +0 -15
  116. package/dist/prompts/templates/review/ci-classification.md +0 -9
  117. package/dist/prompts/templates/review/close-reconsideration.md +0 -6
  118. /package/dist/{types.js → config/index.type.js} +0 -0
  119. /package/dist/prompts/{templates/triage/acceptance.md → triage/acceptance/task.md} +0 -0
  120. /package/dist/prompts/{templates/triage/category.md → triage/category/task.md} +0 -0
  121. /package/dist/prompts/{templates/triage/comment-classification.md → triage/comment-classification/task.md} +0 -0
  122. /package/dist/prompts/{templates/triage/create.md → triage/create/task.md} +0 -0
  123. /package/dist/prompts/{templates/triage/duplicate.md → triage/deplicate/task.md} +0 -0
  124. /package/dist/prompts/{templates/triage/existing-pr.md → triage/existing/task.md} +0 -0
  125. /package/dist/prompts/{templates/triage/reconsider.md → triage/reconsider/task.md} +0 -0
  126. /package/dist/prompts/{templates/triage/signal.md → triage/signal/task.md} +0 -0
@@ -1,88 +0,0 @@
1
- import { majorityThreshold } from "./majority";
2
- function validationFindings(output) {
3
- if ("findings" in output)
4
- return output.findings;
5
- return output.newFindings.map((finding) => ({
6
- fix: "Please address this before merging.",
7
- issue: finding.body,
8
- line: finding.line,
9
- path: finding.path,
10
- startLine: finding.startLine,
11
- }));
12
- }
13
- export function reviewFindingTargets(outputs) {
14
- return Object.entries(outputs).flatMap(([reviewer, output]) => {
15
- if (output.verdict !== "CHANGES_REQUESTED")
16
- return [];
17
- return validationFindings(output).map((finding, findingIndex) => ({
18
- finding,
19
- findingIndex,
20
- reviewer,
21
- }));
22
- });
23
- }
24
- export function validateFindingVotes(input) {
25
- const expected = input.targets.filter((target) => target.reviewer !== input.validator);
26
- const expectedKeys = new Set(expected.map((target) => `${target.reviewer}:${target.findingIndex}`));
27
- const seen = new Set();
28
- for (const vote of input.output.votes) {
29
- if (vote.reviewer === input.validator) {
30
- throw new Error(`${input.validator} must not vote on its own findings`);
31
- }
32
- const key = `${vote.reviewer}:${vote.findingIndex}`;
33
- if (!expectedKeys.has(key))
34
- throw new Error(`unexpected finding vote: ${key}`);
35
- if (seen.has(key))
36
- throw new Error(`duplicate finding vote: ${key}`);
37
- seen.add(key);
38
- }
39
- for (const target of expected) {
40
- const key = `${target.reviewer}:${target.findingIndex}`;
41
- if (!seen.has(key))
42
- throw new Error(`missing finding vote: ${key}`);
43
- }
44
- }
45
- export function applyFindingValidation(input) {
46
- const threshold = majorityThreshold(input.reviewerKeys.length);
47
- const kept = [];
48
- const discarded = [];
49
- const next = {};
50
- for (const [reviewer, output] of Object.entries(input.outputs)) {
51
- if (output.verdict !== "CHANGES_REQUESTED") {
52
- next[reviewer] = output;
53
- continue;
54
- }
55
- const keptIndexes = new Set();
56
- const findings = validationFindings(output);
57
- findings.forEach((finding, findingIndex) => {
58
- let agrees = 1;
59
- for (const validator of input.reviewerKeys) {
60
- if (validator === reviewer)
61
- continue;
62
- const vote = input.validations[validator]?.votes.find((item) => item.reviewer === reviewer && item.findingIndex === findingIndex);
63
- if (vote?.vote === "AGREE")
64
- agrees += 1;
65
- }
66
- const target = { finding, findingIndex, reviewer };
67
- if (agrees >= threshold) {
68
- kept.push(target);
69
- keptIndexes.add(findingIndex);
70
- return;
71
- }
72
- discarded.push(target);
73
- });
74
- if ("findings" in output) {
75
- const keptFindings = output.findings.filter((_finding, index) => keptIndexes.has(index));
76
- next[reviewer] = keptFindings.length
77
- ? { ...output, findings: keptFindings }
78
- : { findings: [], verdict: "MERGE" };
79
- continue;
80
- }
81
- const newFindings = output.newFindings.filter((_finding, index) => keptIndexes.has(index));
82
- next[reviewer] =
83
- newFindings.length || output.followUps.length
84
- ? { ...output, newFindings }
85
- : { ...output, newFindings, verdict: "MERGE" };
86
- }
87
- return { outputs: next, summary: { discarded, kept } };
88
- }
@@ -1,73 +0,0 @@
1
- function parseDiffPath(value) {
2
- if (value === "/dev/null")
3
- return undefined;
4
- let path = value;
5
- if (path.startsWith('"') && path.endsWith('"')) {
6
- try {
7
- path = JSON.parse(path);
8
- }
9
- catch {
10
- path = path.slice(1, -1);
11
- }
12
- }
13
- return path.startsWith("b/") ? path.slice(2) : path;
14
- }
15
- function addTargetLine(targets, path, line) {
16
- const lines = targets.get(path) ?? new Set();
17
- lines.add(line);
18
- targets.set(path, lines);
19
- }
20
- export function parseRightSideDiffTargets(diff) {
21
- const targets = new Map();
22
- let currentPath;
23
- let rightLine;
24
- for (const line of diff.split("\n")) {
25
- if (line.startsWith("+++ ")) {
26
- currentPath = parseDiffPath(line.slice(4));
27
- rightLine = undefined;
28
- continue;
29
- }
30
- if (line.startsWith("@@ ")) {
31
- const match = line.match(/\+(\d+)(?:,\d+)?/);
32
- rightLine = match ? Number(match[1]) : undefined;
33
- continue;
34
- }
35
- if (!currentPath || rightLine == null)
36
- continue;
37
- if (line.startsWith("+") || line.startsWith(" ")) {
38
- addTargetLine(targets, currentPath, rightLine);
39
- rightLine += 1;
40
- continue;
41
- }
42
- if (line.startsWith("-"))
43
- continue;
44
- }
45
- return targets;
46
- }
47
- function assertPositiveInteger(value, name) {
48
- if (!Number.isInteger(value) || value < 1) {
49
- throw new Error(`${name} must be a positive integer`);
50
- }
51
- }
52
- export function validateInlineCommentTargets(findings, targets, label = "findings") {
53
- for (const [index, finding] of findings.entries()) {
54
- const name = `${label}[${index}]`;
55
- assertPositiveInteger(finding.line, `${name}.line`);
56
- if (finding.startLine != null) {
57
- assertPositiveInteger(finding.startLine, `${name}.startLine`);
58
- if (finding.startLine > finding.line) {
59
- throw new Error(`${name}.startLine must be before or equal to line`);
60
- }
61
- }
62
- const lines = targets.get(finding.path);
63
- if (!lines) {
64
- throw new Error(`${name} targets ${finding.path}:${finding.line}, but path is not in the PR diff`);
65
- }
66
- const startLine = finding.startLine ?? finding.line;
67
- for (let line = startLine; line <= finding.line; line += 1) {
68
- if (!lines.has(line)) {
69
- throw new Error(`${name} targets ${finding.path}:${line}, but line is not in a right-side PR diff hunk`);
70
- }
71
- }
72
- }
73
- }
@@ -1,62 +0,0 @@
1
- const VERDICTS = ["MERGE", "CHANGES_REQUESTED", "CLOSE"];
2
- export function majorityThreshold(total) {
3
- return Math.floor(total / 2) + 1;
4
- }
5
- export function aggregateStringMajority(results, votes) {
6
- if (results.length < 3 || results.length % 2 === 0) {
7
- throw new Error("majority requires an odd number of at least 3 results");
8
- }
9
- const counts = Object.fromEntries(votes.map((vote) => [vote, 0]));
10
- const voters = Object.fromEntries(votes.map((vote) => [vote, []]));
11
- for (const result of results) {
12
- counts[result.vote] += 1;
13
- voters[result.vote].push(result.voter);
14
- }
15
- const threshold = majorityThreshold(results.length);
16
- const vote = votes.find((item) => counts[item] >= threshold);
17
- return { counts, threshold, vote, voters };
18
- }
19
- export function aggregateMajority(results) {
20
- if (results.length < 3 || results.length % 2 === 0) {
21
- throw new Error("majority requires an odd number of at least 3 reviewer results");
22
- }
23
- const counts = {
24
- CHANGES_REQUESTED: 0,
25
- CLOSE: 0,
26
- MERGE: 0,
27
- };
28
- const reviewers = {
29
- CHANGES_REQUESTED: [],
30
- CLOSE: [],
31
- MERGE: [],
32
- };
33
- for (const result of results) {
34
- counts[result.verdict] += 1;
35
- reviewers[result.verdict].push(result.reviewer);
36
- }
37
- const threshold = majorityThreshold(results.length);
38
- const verdict = VERDICTS.find((item) => counts[item] >= threshold);
39
- if (!verdict)
40
- throw new Error("no majority verdict");
41
- return { counts, reviewers, threshold, verdict };
42
- }
43
- export function reviewOutputsToVerdicts(outputs) {
44
- return Object.entries(outputs).map(([reviewer, output]) => ({
45
- reviewer,
46
- verdict: output.verdict,
47
- }));
48
- }
49
- export function mergeVerdictForPolicy(results, policy) {
50
- const majority = aggregateMajority(results);
51
- if (majority.verdict === "CLOSE")
52
- return "CLOSE";
53
- if (policy === "majority")
54
- return majority.verdict;
55
- return majority.counts.MERGE === results.length
56
- ? "MERGE"
57
- : "CHANGES_REQUESTED";
58
- }
59
- export function closeMinorityReviewers(results) {
60
- const majority = aggregateMajority(results);
61
- return majority.verdict === "CLOSE" ? [] : majority.reviewers.CLOSE;
62
- }