Skip to content

Commit ce9e432

Browse files
authored
Merge pull request #1662 from msu8/AISDLC-311
feat(triage): add move action to result schema
2 parents a159f38 + 477ea46 commit ce9e432

2 files changed

Lines changed: 94 additions & 14 deletions

File tree

‎schemas/triage-result.schema.json‎

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"properties": {
1010
"action": {
1111
"type": "string",
12-
"enum": ["insufficient", "duplicate", "sufficient", "prerequisites", "in-progress", "question", "not-planned", "completed", "split"]
12+
"enum": ["insufficient", "duplicate", "sufficient", "prerequisites", "in-progress", "question", "not-planned", "completed", "split", "move"]
1313
},
1414
"reasoning": {
1515
"type": "string",
@@ -33,6 +33,9 @@
3333
"triage_summary": {
3434
"$ref": "#/$defs/triage_summary"
3535
},
36+
"move_to": {
37+
"$ref": "#/$defs/move_to"
38+
},
3639
"pull_requests": {
3740
"type": "array",
3841
"minItems": 1,
@@ -80,12 +83,7 @@
8083
"required": ["repo", "title", "body"],
8184
"properties": {
8285
"repo": {
83-
"type": "string",
84-
"description": "GitHub/GitLab path-style identifier (org/repo) or bare Jira project key (e.g. PROJ). Consumers should handle both formats.",
85-
"anyOf": [
86-
{ "pattern": "^[a-zA-Z0-9._-]+(/[a-zA-Z0-9._-]+)+$" },
87-
{ "pattern": "^[A-Z][A-Z0-9]*$" }
88-
]
86+
"$ref": "#/$defs/issue_target"
8987
},
9088
"title": {
9189
"type": "string",
@@ -110,12 +108,7 @@
110108
"required": ["title", "body"],
111109
"properties": {
112110
"repo": {
113-
"type": "string",
114-
"description": "GitHub/GitLab path-style identifier (org/repo) or bare Jira project key (e.g. PROJ). Consumers should handle both formats.",
115-
"anyOf": [
116-
{ "pattern": "^[a-zA-Z0-9._-]+(/[a-zA-Z0-9._-]+)+$" },
117-
{ "pattern": "^[A-Z][A-Z0-9]*$" }
118-
]
111+
"$ref": "#/$defs/issue_target"
119112
},
120113
"title": {
121114
"type": "string",
@@ -170,9 +163,25 @@
170163
{
171164
"if": { "properties": { "action": { "const": "split" } }, "required": ["action"] },
172165
"then": { "required": ["sub_issues"] }
166+
},
167+
{
168+
"if": { "properties": { "action": { "const": "move" } }, "required": ["action"] },
169+
"then": {
170+
"required": ["move_to"],
171+
"not": { "required": ["triage_summary"] }
172+
}
173173
}
174174
],
175175
"$defs": {
176+
"issue_target": {
177+
"type": "string",
178+
"description": "GitHub/GitLab destination repository path (org/repo) or Jira destination project key (e.g. PROJ). The consumer must still verify that the target is allowed and movable.",
179+
"anyOf": [
180+
{ "pattern": "^[a-zA-Z0-9._-]+(/[a-zA-Z0-9._-]+)+$" },
181+
{ "pattern": "^[A-Z][A-Z0-9]*$" }
182+
],
183+
"not": { "pattern": "[\\r\\n]|(^|/)\\.{1,2}(/|$)" }
184+
},
176185
"clarity_scores": {
177186
"type": "object",
178187
"required": ["symptom", "cause", "reproduction", "impact", "overall"],
@@ -208,6 +217,21 @@
208217
},
209218
"additionalProperties": false
210219
},
220+
"move_to": {
221+
"type": "object",
222+
"description": "Destination for the move action. target is org/repo for GitHub/GitLab or a Jira project key (e.g. OTHERPROJ). Platform-specific validation (same-owner, issue type compatibility) is handled by the consumer, not the schema.",
223+
"required": ["target"],
224+
"properties": {
225+
"target": {
226+
"$ref": "#/$defs/issue_target"
227+
},
228+
"evidence": {
229+
"type": "array",
230+
"items": { "type": "string" }
231+
}
232+
},
233+
"additionalProperties": false
234+
},
211235
"label_actions": {
212236
"type": "object",
213237
"required": ["reason", "actions"],

‎scripts/validate-output-schema-test.sh‎

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,18 @@ run_test "valid-split" \
106106
'{"action":"split","reasoning":"issue bundles independent concerns","sub_issues":[{"title":"Fix crash on save","body":"The save handler crashes when input is empty."},{"title":"Update error messages","body":"Error messages are outdated."}],"comment":"Splitting into independent sub-issues."}' \
107107
"true"
108108

109+
run_test "valid-move-without-evidence" \
110+
'{"action":"move","reasoning":"the affected code is maintained elsewhere","move_to":{"target":"org/other-repo"},"comment":"Moving this issue to the repository that owns the affected code."}' \
111+
"true"
112+
113+
run_test "valid-move-with-evidence" \
114+
'{"action":"move","reasoning":"the affected code is maintained elsewhere","move_to":{"target":"org/other-repo","evidence":["The affected package lives in org/other-repo."]},"comment":"Moving this issue to the repository that owns the affected code."}' \
115+
"true"
116+
117+
run_test "valid-move-jira-project-key" \
118+
'{"action":"move","reasoning":"the issue belongs to another Jira project","move_to":{"target":"OTHERPROJ"},"comment":"Moving this issue to the owning Jira project."}' \
119+
"true"
120+
109121
# --- Jira tracker shapes ---
110122
# duplicate_of is an integer on GitHub/GitLab but a full issue key on Jira.
111123
run_test "valid-jira-duplicate-key" \
@@ -136,6 +148,50 @@ run_test "sufficient-missing-triage-summary" \
136148
'{"action":"sufficient","reasoning":"ok","clarity_scores":{"symptom":0.9,"cause":0.8,"reproduction":0.9,"impact":0.7,"overall":0.85},"comment":"Done."}' \
137149
"false"
138150

151+
run_test "move-missing-move-to" \
152+
'{"action":"move","reasoning":"owned elsewhere","comment":"Moving this issue."}' \
153+
"false"
154+
155+
run_test "move-missing-target" \
156+
'{"action":"move","reasoning":"owned elsewhere","move_to":{},"comment":"Moving this issue."}' \
157+
"false"
158+
159+
run_test "move-empty-target" \
160+
'{"action":"move","reasoning":"owned elsewhere","move_to":{"target":""},"comment":"Moving this issue."}' \
161+
"false"
162+
163+
run_test "move-url-target" \
164+
'{"action":"move","reasoning":"owned elsewhere","move_to":{"target":"https://github.com/org/other-repo"},"comment":"Moving this issue."}' \
165+
"false"
166+
167+
run_test "move-whitespace-target" \
168+
'{"action":"move","reasoning":"owned elsewhere","move_to":{"target":" "},"comment":"Moving this issue."}' \
169+
"false"
170+
171+
run_test "move-newline-target" \
172+
'{"action":"move","reasoning":"owned elsewhere","move_to":{"target":"org/other-repo\n::set-output name=target::malicious"},"comment":"Moving this issue."}' \
173+
"false"
174+
175+
run_test "move-trailing-newline-target" \
176+
'{"action":"move","reasoning":"owned elsewhere","move_to":{"target":"org/other-repo\n"},"comment":"Moving this issue."}' \
177+
"false"
178+
179+
run_test "move-dot-segment-target" \
180+
'{"action":"move","reasoning":"owned elsewhere","move_to":{"target":"org/.."},"comment":"Moving this issue."}' \
181+
"false"
182+
183+
run_test "move-parent-path-target" \
184+
'{"action":"move","reasoning":"owned elsewhere","move_to":{"target":"../.."},"comment":"Moving this issue."}' \
185+
"false"
186+
187+
run_test "move-malformed-evidence" \
188+
'{"action":"move","reasoning":"owned elsewhere","move_to":{"target":"org/other-repo","evidence":["valid evidence",42]},"comment":"Moving this issue."}' \
189+
"false"
190+
191+
run_test "move-with-triage-summary-rejected" \
192+
'{"action":"move","reasoning":"owned elsewhere","move_to":{"target":"org/other-repo"},"triage_summary":{"title":"Bug","severity":"high","category":"bug","problem":"crash","root_cause_hypothesis":"null ptr","reproduction_steps":["step 1"],"impact":"all users","recommended_fix":"fix ptr","proposed_test_case":"test_fix","promote_to_ready_to_code":true},"comment":"Moving this issue."}' \
193+
"false"
194+
139195
run_test "prerequisites-missing-prerequisites-field" \
140196
'{"action":"prerequisites","reasoning":"upstream dependency","comment":"Blocked."}' \
141197
"false"
@@ -400,7 +456,7 @@ run_test_output "additional-properties-shows-allowed" \
400456
run_test_output "additional-properties-lists-known-keys" \
401457
'{"action":"sufficient","reasoning":"ok","clarity_scores":{"symptom":0.9,"cause":0.8,"reproduction":0.9,"impact":0.7,"overall":0.85},"triage_summary":{"title":"Bug","severity":"high","category":"bug","problem":"crash","root_cause_hypothesis":"null ptr","reproduction_steps":["step 1"],"impact":"all users","recommended_fix":"fix","proposed_test_case":"test"},"comment":"Done.","injected_field":"malicious"}' \
402458
"false" \
403-
"action, clarity_scores, comment, component_actions, duplicate_of, label_actions, prerequisites, pull_requests, reasoning, sub_issues, triage_summary"
459+
"action, clarity_scores, comment, component_actions, duplicate_of, label_actions, move_to, prerequisites, pull_requests, reasoning, sub_issues, triage_summary"
404460

405461
run_test_output "valid-output-no-allowed-line" \
406462
'{"action":"insufficient","reasoning":"missing repro","clarity_scores":{"symptom":0.6,"cause":0.3,"reproduction":0.1,"impact":0.5,"overall":0.39},"comment":"Can you share repro steps?"}' \

0 commit comments

Comments
 (0)