opencode-magi 0.6.1 → 0.8.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.
- package/README.md +16 -6
- package/dist/config/resolve.js +40 -3
- package/dist/config/validate.js +231 -66
- package/dist/github/commands.js +32 -0
- package/dist/index.js +21 -50
- package/dist/orchestrator/merge.js +310 -10
- package/dist/orchestrator/report.js +1 -1
- package/dist/orchestrator/review.js +97 -1
- package/dist/orchestrator/run-manager.js +4 -4
- package/dist/orchestrator/triage.js +312 -103
- package/dist/prompts/compose.js +59 -2
- package/dist/prompts/contracts.js +20 -1
- package/dist/prompts/output.js +19 -1
- package/dist/prompts/templates/merge/conflict.md +10 -0
- package/dist/prompts/templates/review/rereview.md +2 -0
- package/dist/prompts/templates/review/review.md +2 -0
- package/dist/prompts/templates/triage/acceptance.md +1 -1
- package/dist/prompts/templates/triage/signal.md +10 -0
- package/package.json +1 -1
- package/schema.json +89 -16
package/dist/prompts/compose.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { readFile } from "node:fs/promises";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { isAbsolute, join } from "node:path";
|
|
4
|
-
import { ciClassificationAfterEditOutputContract, ciClassificationOutputContract, closeReconsiderationOutputContract, editOutputContract, findingValidationOutputContract, rereviewCloseReconsiderationOutputContract, rereviewOutputContract, reviewOutputContract, triageCommentClassificationOutputContract, triageCreatePrOutputContract, triageDuplicateOutputContract, triageVoteOutputContract, } from "./contracts";
|
|
4
|
+
import { ciClassificationAfterEditOutputContract, ciClassificationOutputContract, closeReconsiderationOutputContract, editOutputContract, findingValidationOutputContract, rereviewCloseReconsiderationOutputContract, rereviewOutputContract, reviewOutputContract, triageCommentClassificationOutputContract, triageCreatePrOutputContract, triageDuplicateOutputContract, triageSignalOutputContract, triageVoteOutputContract, } from "./contracts";
|
|
5
5
|
async function readOptionalPrompt(directory, path, values = {}) {
|
|
6
6
|
if (!path)
|
|
7
7
|
return "";
|
|
@@ -35,6 +35,7 @@ function repositoryValues(repository) {
|
|
|
35
35
|
}
|
|
36
36
|
function reviewValues(input) {
|
|
37
37
|
const ciFailureContext = input.ciFailureContext?.trim() ?? "";
|
|
38
|
+
const mergeConflictContext = input.mergeConflictContext?.trim() ?? "";
|
|
38
39
|
return {
|
|
39
40
|
...repositoryValues(input.repository),
|
|
40
41
|
baseSha: input.baseSha,
|
|
@@ -44,6 +45,10 @@ function reviewValues(input) {
|
|
|
44
45
|
: "",
|
|
45
46
|
headSha: input.headSha,
|
|
46
47
|
jsonEncodedWorktreePath: JSON.stringify(input.worktreePath),
|
|
48
|
+
mergeConflictContext,
|
|
49
|
+
mergeConflictContextBlock: mergeConflictContext
|
|
50
|
+
? `<merge_conflict_context>\n${mergeConflictContext}\n</merge_conflict_context>`
|
|
51
|
+
: "",
|
|
47
52
|
pr: String(input.pr),
|
|
48
53
|
reviewContext: input.reviewContext ?? "",
|
|
49
54
|
worktreePath: input.worktreePath,
|
|
@@ -67,6 +72,17 @@ function editValues(input) {
|
|
|
67
72
|
worktreePath: input.worktreePath,
|
|
68
73
|
};
|
|
69
74
|
}
|
|
75
|
+
function mergeConflictValues(input) {
|
|
76
|
+
return {
|
|
77
|
+
...repositoryValues(input.repository),
|
|
78
|
+
baseBranch: input.baseBranch,
|
|
79
|
+
baseSha: input.baseSha,
|
|
80
|
+
conflictedFiles: input.conflictedFiles,
|
|
81
|
+
headSha: input.headSha,
|
|
82
|
+
pr: String(input.pr),
|
|
83
|
+
worktreePath: input.worktreePath,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
70
86
|
function triageValues(input) {
|
|
71
87
|
const categories = input.repository.triage?.categories ?? [];
|
|
72
88
|
const categoryOptions = categories
|
|
@@ -74,12 +90,16 @@ function triageValues(input) {
|
|
|
74
90
|
? `- ${category.id}: ${category.description}`
|
|
75
91
|
: `- ${category.id}`)
|
|
76
92
|
.join("\n");
|
|
93
|
+
const signalOptions = (input.repository.triage?.signals ?? [])
|
|
94
|
+
.map((signal) => `- ${signal.id}: ${signal.description}`)
|
|
95
|
+
.join("\n");
|
|
77
96
|
return {
|
|
78
97
|
...repositoryValues(input.repository),
|
|
79
98
|
author: input.author ?? "",
|
|
80
99
|
categoryOptions,
|
|
81
100
|
context: input.context,
|
|
82
101
|
issue: String(input.issue),
|
|
102
|
+
signalOptions,
|
|
83
103
|
worktreePath: input.worktreePath ?? "",
|
|
84
104
|
};
|
|
85
105
|
}
|
|
@@ -97,6 +117,12 @@ function previousReviewBlock(previousReview) {
|
|
|
97
117
|
function reviewContextBlock(reviewContext) {
|
|
98
118
|
return reviewContext?.trim() ? reviewContext.trim() : "";
|
|
99
119
|
}
|
|
120
|
+
function mergeConflictContextBlock(mergeConflictContext) {
|
|
121
|
+
const body = mergeConflictContext?.trim();
|
|
122
|
+
return body
|
|
123
|
+
? `<merge_conflict_context>\n${body}\n</merge_conflict_context>`
|
|
124
|
+
: "";
|
|
125
|
+
}
|
|
100
126
|
async function reviewGuidelinesBlock(input) {
|
|
101
127
|
const body = (await readOptionalPrompt(input.directory, input.path, input.values)).trim();
|
|
102
128
|
return body ? `<review_guidelines>\n${body}\n</review_guidelines>` : "";
|
|
@@ -136,6 +162,7 @@ export async function composeReviewPrompt(input) {
|
|
|
136
162
|
return [
|
|
137
163
|
task,
|
|
138
164
|
reviewContextBlock(input.reviewContext),
|
|
165
|
+
mergeConflictContextBlock(input.mergeConflictContext),
|
|
139
166
|
languageBlock(input.repository.language),
|
|
140
167
|
personaBlock(input.reviewer.persona),
|
|
141
168
|
await reviewGuidelinesBlock({
|
|
@@ -159,6 +186,7 @@ export async function composeRereviewPrompt(input) {
|
|
|
159
186
|
return [
|
|
160
187
|
task,
|
|
161
188
|
reviewContextBlock(input.reviewContext),
|
|
189
|
+
mergeConflictContextBlock(input.mergeConflictContext),
|
|
162
190
|
input.includeSessionContext === false
|
|
163
191
|
? ""
|
|
164
192
|
: languageBlock(input.repository.language),
|
|
@@ -200,6 +228,28 @@ export async function composeEditPrompt(input) {
|
|
|
200
228
|
.filter(Boolean)
|
|
201
229
|
.join("\n\n");
|
|
202
230
|
}
|
|
231
|
+
export async function composeMergeConflictPrompt(input) {
|
|
232
|
+
const values = mergeConflictValues(input);
|
|
233
|
+
const task = await taskBlock({
|
|
234
|
+
builtin: "merge/conflict",
|
|
235
|
+
directory: input.directory,
|
|
236
|
+
values,
|
|
237
|
+
});
|
|
238
|
+
const persona = input.repository.agents.editor?.persona;
|
|
239
|
+
return [
|
|
240
|
+
task,
|
|
241
|
+
languageBlock(input.repository.language),
|
|
242
|
+
personaBlock(persona),
|
|
243
|
+
await editGuidelinesBlock({
|
|
244
|
+
directory: input.directory,
|
|
245
|
+
path: input.repository.prompts.editGuidelines,
|
|
246
|
+
values,
|
|
247
|
+
}),
|
|
248
|
+
editOutputContract,
|
|
249
|
+
]
|
|
250
|
+
.filter(Boolean)
|
|
251
|
+
.join("\n\n");
|
|
252
|
+
}
|
|
203
253
|
export async function composeFindingValidationPrompt(input) {
|
|
204
254
|
const values = { ...reviewValues(input), findings: input.findings };
|
|
205
255
|
const task = await taskBlock({
|
|
@@ -395,7 +445,14 @@ export async function composeTriageAcceptancePrompt(input) {
|
|
|
395
445
|
...input,
|
|
396
446
|
builtin: "acceptance",
|
|
397
447
|
customPath: input.repository.triage?.prompts.acceptance,
|
|
398
|
-
outputContract: triageVoteOutputContract('"YES" | "NO" | "ASK"'),
|
|
448
|
+
outputContract: triageVoteOutputContract('"YES" | "NO" | "INVALID" | "ASK"'),
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
export async function composeTriageSignalPrompt(input) {
|
|
452
|
+
return composeTriageVotePrompt({
|
|
453
|
+
...input,
|
|
454
|
+
builtin: "signal",
|
|
455
|
+
outputContract: triageSignalOutputContract,
|
|
399
456
|
});
|
|
400
457
|
}
|
|
401
458
|
export async function composeTriageCommentClassificationPrompt(input) {
|
|
@@ -256,6 +256,24 @@ The object must match this shape:
|
|
|
256
256
|
]
|
|
257
257
|
}
|
|
258
258
|
</output_contract>`.trim();
|
|
259
|
+
export const triageSignalOutputContract = `
|
|
260
|
+
<output_contract>
|
|
261
|
+
Return exactly one JSON object and nothing else. Do not wrap it in markdown.
|
|
262
|
+
|
|
263
|
+
The object must match this shape:
|
|
264
|
+
{
|
|
265
|
+
"signals": [
|
|
266
|
+
{
|
|
267
|
+
"id": "configured_signal_id",
|
|
268
|
+
"reason": "Short rationale."
|
|
269
|
+
}
|
|
270
|
+
]
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
Rules:
|
|
274
|
+
- Return only configured signal IDs that apply.
|
|
275
|
+
- Return an empty signals array when none apply.
|
|
276
|
+
</output_contract>`.trim();
|
|
259
277
|
const outputContractsBySchemaName = {
|
|
260
278
|
"CI classification": ciClassificationOutputContract,
|
|
261
279
|
"close reconsideration": closeReconsiderationOutputContract,
|
|
@@ -264,13 +282,14 @@ const outputContractsBySchemaName = {
|
|
|
264
282
|
rereview: rereviewOutputContract,
|
|
265
283
|
"rereview close reconsideration": rereviewCloseReconsiderationOutputContract,
|
|
266
284
|
review: reviewOutputContract,
|
|
267
|
-
"triage acceptance": triageVoteOutputContract('"YES" | "NO" | "ASK"'),
|
|
285
|
+
"triage acceptance": triageVoteOutputContract('"YES" | "NO" | "INVALID" | "ASK"'),
|
|
268
286
|
"triage category": triageVoteOutputContract('"ASK" or one of the configured category IDs'),
|
|
269
287
|
"triage create PR": triageCreatePrOutputContract,
|
|
270
288
|
"triage comment classification": triageCommentClassificationOutputContract,
|
|
271
289
|
"triage duplicate": triageDuplicateOutputContract,
|
|
272
290
|
"triage existing PR": triageVoteOutputContract('"RELATED_PR_HANDLES_ISSUE" | "RELATED_PR_DOES_NOT_HANDLE_ISSUE"'),
|
|
273
291
|
"triage reconsider": triageVoteOutputContract('"YES" | "NO" | "ASK"'),
|
|
292
|
+
"triage signal": triageSignalOutputContract,
|
|
274
293
|
};
|
|
275
294
|
export function repairPrompt(schemaName) {
|
|
276
295
|
const outputContract = outputContractsBySchemaName[schemaName];
|
package/dist/prompts/output.js
CHANGED
|
@@ -112,7 +112,25 @@ export function parseTriageCategoryOutput(text, categories) {
|
|
|
112
112
|
return parseTriageVote(text, ["ASK", ...categories]);
|
|
113
113
|
}
|
|
114
114
|
export function parseTriageBinaryOutput(text) {
|
|
115
|
-
return parseTriageVote(text, ["ASK", "NO", "YES"]);
|
|
115
|
+
return parseTriageVote(text, ["ASK", "INVALID", "NO", "YES"]);
|
|
116
|
+
}
|
|
117
|
+
export function parseTriageSignalOutput(text, signalIds) {
|
|
118
|
+
const data = extractJson(text);
|
|
119
|
+
if (!data || typeof data !== "object")
|
|
120
|
+
throw new Error("triage signal output must be an object");
|
|
121
|
+
const ids = new Set(signalIds);
|
|
122
|
+
return {
|
|
123
|
+
signals: requireArray(data.signals, "signals").map((item, index) => {
|
|
124
|
+
const value = item;
|
|
125
|
+
const id = requireString(value.id, `signals[${index}].id`);
|
|
126
|
+
if (!ids.has(id))
|
|
127
|
+
throw new Error(`signals[${index}].id is not configured`);
|
|
128
|
+
return {
|
|
129
|
+
id,
|
|
130
|
+
reason: requireString(value.reason, `signals[${index}].reason`),
|
|
131
|
+
};
|
|
132
|
+
}),
|
|
133
|
+
};
|
|
116
134
|
}
|
|
117
135
|
export function parseTriageDuplicateOutput(text) {
|
|
118
136
|
const data = extractJson(text);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Resolve merge conflicts for pull request #{pr} in {owner}/{repo}.
|
|
2
|
+
The PR worktree is {worktreePath}.
|
|
3
|
+
|
|
4
|
+
The latest base branch is {baseBranch} at {baseSha}.
|
|
5
|
+
The PR head before conflict recovery was {headSha}.
|
|
6
|
+
|
|
7
|
+
Conflicted files:
|
|
8
|
+
{conflictedFiles}
|
|
9
|
+
|
|
10
|
+
Resolve every merge conflict in the worktree. Preserve the intended PR behavior while incorporating the latest base branch changes. Stage all resolved files and create a commit. Do not push.
|
|
@@ -13,6 +13,8 @@ Every newFinding must target a valid right-side line in the PR diff.
|
|
|
13
13
|
If the problem itself does not have an exact changed line, choose the nearest changed line that represents the cause, responsibility, missing implementation, or affected behavior. This includes but is not limited to missing validation, missing wiring, missing requirements, missing tests, missing documentation, affected configuration, or relevant call sites.
|
|
14
14
|
Do not omit line. Do not create file-level or body-only newFindings.
|
|
15
15
|
|
|
16
|
+
If `<merge_conflict_context>` is present, treat unresolved merge conflicts as review findings. Request changes when a conflict makes the PR unsafe or impossible to merge, and prefer the provided `suggestedLine` when it is present.
|
|
17
|
+
|
|
16
18
|
{ciFailureContextBlock}
|
|
17
19
|
Do not edit files or perform write operations.
|
|
18
20
|
|
|
@@ -14,4 +14,6 @@ Every finding must target a valid right-side line in the PR diff.
|
|
|
14
14
|
If the problem itself does not have an exact changed line, choose the nearest changed line that represents the cause, responsibility, missing implementation, or affected behavior. This includes but is not limited to missing validation, missing wiring, missing requirements, missing tests, missing documentation, affected configuration, or relevant call sites.
|
|
15
15
|
Do not omit line. Do not create file-level or body-only findings.
|
|
16
16
|
|
|
17
|
+
If `<merge_conflict_context>` is present, treat unresolved merge conflicts as review findings. Request changes when a conflict makes the PR unsafe or impossible to merge, and prefer the provided `suggestedLine` when it is present.
|
|
18
|
+
|
|
17
19
|
{ciFailureContextBlock}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Evaluate issue #{issue} in {owner}/{repo} for the selected category.
|
|
2
2
|
|
|
3
|
-
Choose YES when the issue should be accepted for the project. Choose NO when it should be
|
|
3
|
+
Choose YES when the issue should be accepted for the project. Choose NO when it should not be worked on for normal wontfix reasons. Choose INVALID when the report is unreproducible, contradictory, based on an impossible premise, or otherwise not actionable as an issue. Choose ASK when specific missing information is required before deciding.
|
|
4
4
|
|
|
5
5
|
<context>
|
|
6
6
|
{context}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
Evaluate optional triage signals for issue #{issue} in {owner}/{repo}.
|
|
2
|
+
|
|
3
|
+
Configured signals:
|
|
4
|
+
{signalOptions}
|
|
5
|
+
|
|
6
|
+
Return every configured signal that applies to the final triage result and issue context. Do not invent signal IDs.
|
|
7
|
+
|
|
8
|
+
<context>
|
|
9
|
+
{context}
|
|
10
|
+
</context>
|
package/package.json
CHANGED
package/schema.json
CHANGED
|
@@ -60,8 +60,7 @@
|
|
|
60
60
|
"additionalProperties": false,
|
|
61
61
|
"properties": {
|
|
62
62
|
"id": { "type": "string", "pattern": "^[A-Za-z0-9_-]+$" },
|
|
63
|
-
"model": { "
|
|
64
|
-
"options": { "type": "object", "additionalProperties": true },
|
|
63
|
+
"model": { "$ref": "#/$defs/modelConfig" },
|
|
65
64
|
"account": { "type": "string", "minLength": 1 },
|
|
66
65
|
"author": {
|
|
67
66
|
"type": "object",
|
|
@@ -83,8 +82,7 @@
|
|
|
83
82
|
"properties": {
|
|
84
83
|
"ref": { "type": "string", "minLength": 1 },
|
|
85
84
|
"id": { "type": "string", "pattern": "^[A-Za-z0-9_-]+$" },
|
|
86
|
-
"model": { "
|
|
87
|
-
"options": { "type": "object", "additionalProperties": true },
|
|
85
|
+
"model": { "$ref": "#/$defs/modelConfig" },
|
|
88
86
|
"account": { "type": "string", "minLength": 1 },
|
|
89
87
|
"permissions": { "$ref": "#/$defs/permissions" },
|
|
90
88
|
"persona": { "type": "string" }
|
|
@@ -97,8 +95,7 @@
|
|
|
97
95
|
"additionalProperties": false,
|
|
98
96
|
"properties": {
|
|
99
97
|
"ref": { "type": "string", "minLength": 1 },
|
|
100
|
-
"model": { "
|
|
101
|
-
"options": { "type": "object", "additionalProperties": true },
|
|
98
|
+
"model": { "$ref": "#/$defs/modelConfig" },
|
|
102
99
|
"account": { "type": "string", "minLength": 1 },
|
|
103
100
|
"author": {
|
|
104
101
|
"type": "object",
|
|
@@ -121,9 +118,8 @@
|
|
|
121
118
|
"properties": {
|
|
122
119
|
"ref": { "type": "string", "minLength": 1 },
|
|
123
120
|
"id": { "type": "string", "pattern": "^[A-Za-z0-9_-]+$" },
|
|
124
|
-
"model": { "
|
|
121
|
+
"model": { "$ref": "#/$defs/modelConfig" },
|
|
125
122
|
"account": { "type": "string", "minLength": 1 },
|
|
126
|
-
"options": { "type": "object", "additionalProperties": true },
|
|
127
123
|
"permissions": { "$ref": "#/$defs/permissions" },
|
|
128
124
|
"persona": { "type": "string" }
|
|
129
125
|
}
|
|
@@ -136,8 +132,7 @@
|
|
|
136
132
|
"properties": {
|
|
137
133
|
"ref": { "type": "string", "minLength": 1 },
|
|
138
134
|
"account": { "type": "string", "minLength": 1 },
|
|
139
|
-
"model": { "
|
|
140
|
-
"options": { "type": "object", "additionalProperties": true },
|
|
135
|
+
"model": { "$ref": "#/$defs/modelConfig" },
|
|
141
136
|
"author": {
|
|
142
137
|
"type": "object",
|
|
143
138
|
"required": ["name", "email"],
|
|
@@ -151,6 +146,31 @@
|
|
|
151
146
|
"persona": { "type": "string" }
|
|
152
147
|
}
|
|
153
148
|
},
|
|
149
|
+
"modelConfig": {
|
|
150
|
+
"oneOf": [
|
|
151
|
+
{ "type": "string", "minLength": 1 },
|
|
152
|
+
{ "$ref": "#/$defs/modelCandidate" },
|
|
153
|
+
{
|
|
154
|
+
"type": "array",
|
|
155
|
+
"minItems": 1,
|
|
156
|
+
"items": {
|
|
157
|
+
"oneOf": [
|
|
158
|
+
{ "type": "string", "minLength": 1 },
|
|
159
|
+
{ "$ref": "#/$defs/modelCandidate" }
|
|
160
|
+
]
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
]
|
|
164
|
+
},
|
|
165
|
+
"modelCandidate": {
|
|
166
|
+
"type": "object",
|
|
167
|
+
"required": ["id"],
|
|
168
|
+
"additionalProperties": false,
|
|
169
|
+
"properties": {
|
|
170
|
+
"id": { "type": "string", "minLength": 1 },
|
|
171
|
+
"options": { "type": "object", "additionalProperties": true }
|
|
172
|
+
}
|
|
173
|
+
},
|
|
154
174
|
"automation": {
|
|
155
175
|
"type": "object",
|
|
156
176
|
"additionalProperties": false,
|
|
@@ -159,6 +179,15 @@
|
|
|
159
179
|
"close": { "type": "boolean" }
|
|
160
180
|
}
|
|
161
181
|
},
|
|
182
|
+
"mergeAutomation": {
|
|
183
|
+
"type": "object",
|
|
184
|
+
"additionalProperties": false,
|
|
185
|
+
"properties": {
|
|
186
|
+
"merge": { "type": "boolean", "default": true },
|
|
187
|
+
"close": { "type": "boolean", "default": false },
|
|
188
|
+
"conflict": { "type": "boolean", "default": false }
|
|
189
|
+
}
|
|
190
|
+
},
|
|
162
191
|
"reviewChecks": {
|
|
163
192
|
"type": "object",
|
|
164
193
|
"additionalProperties": false,
|
|
@@ -250,6 +279,47 @@
|
|
|
250
279
|
"description": { "type": "string" }
|
|
251
280
|
}
|
|
252
281
|
},
|
|
282
|
+
"triageSignal": {
|
|
283
|
+
"type": "object",
|
|
284
|
+
"additionalProperties": false,
|
|
285
|
+
"required": ["id", "description"],
|
|
286
|
+
"properties": {
|
|
287
|
+
"id": { "type": "string", "pattern": "^[A-Za-z0-9_-]+$" },
|
|
288
|
+
"description": { "type": "string", "minLength": 1 }
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
"triageLabelRuleCondition": {
|
|
292
|
+
"type": "object",
|
|
293
|
+
"additionalProperties": false,
|
|
294
|
+
"minProperties": 1,
|
|
295
|
+
"properties": {
|
|
296
|
+
"disposition": {
|
|
297
|
+
"enum": [
|
|
298
|
+
"accepted",
|
|
299
|
+
"rejected",
|
|
300
|
+
"invalid",
|
|
301
|
+
"duplicate",
|
|
302
|
+
"already_handled",
|
|
303
|
+
"needs_category",
|
|
304
|
+
"needs_acceptance",
|
|
305
|
+
"blocked",
|
|
306
|
+
"failed"
|
|
307
|
+
]
|
|
308
|
+
},
|
|
309
|
+
"category": { "type": "string" },
|
|
310
|
+
"signals": { "type": "array", "items": { "type": "string" } }
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
"triageLabelRule": {
|
|
314
|
+
"type": "object",
|
|
315
|
+
"additionalProperties": false,
|
|
316
|
+
"required": ["when"],
|
|
317
|
+
"properties": {
|
|
318
|
+
"when": { "$ref": "#/$defs/triageLabelRuleCondition" },
|
|
319
|
+
"add": { "type": "array", "items": { "type": "string" } },
|
|
320
|
+
"remove": { "type": "array", "items": { "type": "string" } }
|
|
321
|
+
}
|
|
322
|
+
},
|
|
253
323
|
"triageAutomation": {
|
|
254
324
|
"type": "object",
|
|
255
325
|
"additionalProperties": false,
|
|
@@ -258,10 +328,9 @@
|
|
|
258
328
|
"create": { "type": "boolean", "default": false },
|
|
259
329
|
"review": { "type": "boolean", "default": false },
|
|
260
330
|
"merge": { "type": "boolean", "default": false },
|
|
261
|
-
"
|
|
331
|
+
"label": {
|
|
262
332
|
"type": "array",
|
|
263
|
-
"items": { "
|
|
264
|
-
"default": ["triage"]
|
|
333
|
+
"items": { "$ref": "#/$defs/triageLabelRule" }
|
|
265
334
|
}
|
|
266
335
|
}
|
|
267
336
|
},
|
|
@@ -297,7 +366,7 @@
|
|
|
297
366
|
"type": "object",
|
|
298
367
|
"additionalProperties": false,
|
|
299
368
|
"properties": {
|
|
300
|
-
"
|
|
369
|
+
"reviewers": {
|
|
301
370
|
"type": "array",
|
|
302
371
|
"minItems": 3,
|
|
303
372
|
"items": { "$ref": "#/$defs/reviewer" }
|
|
@@ -319,7 +388,7 @@
|
|
|
319
388
|
"editor": { "$ref": "#/$defs/editor" },
|
|
320
389
|
"checks": { "$ref": "#/$defs/mergeChecks" },
|
|
321
390
|
"prompts": { "$ref": "#/$defs/mergePrompts" },
|
|
322
|
-
"automation": { "$ref": "#/$defs/
|
|
391
|
+
"automation": { "$ref": "#/$defs/mergeAutomation" },
|
|
323
392
|
"maxThreadResolutionCycles": {
|
|
324
393
|
"type": "integer",
|
|
325
394
|
"minimum": 0,
|
|
@@ -332,7 +401,7 @@
|
|
|
332
401
|
"type": "object",
|
|
333
402
|
"additionalProperties": false,
|
|
334
403
|
"properties": {
|
|
335
|
-
"
|
|
404
|
+
"voters": {
|
|
336
405
|
"type": "array",
|
|
337
406
|
"minItems": 3,
|
|
338
407
|
"items": { "$ref": "#/$defs/triageAgent" }
|
|
@@ -342,6 +411,10 @@
|
|
|
342
411
|
"type": "array",
|
|
343
412
|
"items": { "$ref": "#/$defs/triageCategory" }
|
|
344
413
|
},
|
|
414
|
+
"signals": {
|
|
415
|
+
"type": "array",
|
|
416
|
+
"items": { "$ref": "#/$defs/triageSignal" }
|
|
417
|
+
},
|
|
345
418
|
"automation": { "$ref": "#/$defs/triageAutomation" },
|
|
346
419
|
"safety": { "$ref": "#/$defs/triageSafety" },
|
|
347
420
|
"concurrency": { "$ref": "#/$defs/triageConcurrency" },
|