@sweny-ai/core 0.1.148 → 0.1.150
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/dist/cli/builtin-workflows.d.ts +45 -0
- package/dist/cli/builtin-workflows.js +129 -0
- package/dist/cli/check.d.ts +2 -8
- package/dist/cli/check.js +2 -34
- package/dist/cli/config.js +8 -3
- package/dist/cli/main.js +46 -11
- package/dist/cli/packs.d.ts +9 -5
- package/dist/cli/packs.js +100 -50
- package/dist/executor.js +15 -3
- package/dist/harness/acp-rpc.d.ts +75 -0
- package/dist/harness/acp-rpc.js +204 -0
- package/dist/harness/acp.d.ts +189 -0
- package/dist/harness/acp.js +942 -0
- package/dist/harness/agents.d.ts +5 -1
- package/dist/harness/agents.js +8 -1
- package/dist/harness/auth.d.ts +38 -0
- package/dist/harness/auth.js +93 -0
- package/dist/harness/capabilities.d.ts +30 -0
- package/dist/harness/capabilities.js +41 -0
- package/dist/harness/claude-code.d.ts +8 -0
- package/dist/harness/claude-code.js +8 -1
- package/dist/harness/codex.d.ts +10 -1
- package/dist/harness/codex.js +17 -3
- package/dist/harness/index.d.ts +7 -3
- package/dist/harness/index.js +7 -2
- package/dist/harness/parse.d.ts +12 -0
- package/dist/harness/parse.js +1 -1
- package/dist/harness/policy.js +6 -0
- package/dist/harness/types.d.ts +6 -0
- package/dist/index.d.ts +1 -1
- package/dist/node-policy.js +1 -0
- package/dist/safe-outputs.d.ts +17 -5
- package/dist/safe-outputs.js +85 -11
- package/dist/schema.d.ts +80 -0
- package/dist/schema.js +23 -0
- package/dist/types.d.ts +13 -0
- package/dist/workflows/browser.js +2 -2
- package/dist/workflows/implement.yml +61 -19
- package/dist/workflows/triage.yml +171 -139
- package/package.json +1 -1
|
@@ -3,6 +3,14 @@ name: Alert Triage
|
|
|
3
3
|
workflow_type: monitor
|
|
4
4
|
description: Investigate a production alert, determine root cause, create an issue, implement a fix, and notify the team
|
|
5
5
|
entry: gather
|
|
6
|
+
# Ceiling (#365). `write` because implement and create_pr change code in the
|
|
7
|
+
# checkout and push a branch; every other node narrows to `read`. External
|
|
8
|
+
# writes (issues, comments, the PR) happen only as declared outputs, applied
|
|
9
|
+
# by sweny after the node, within these types and this run-wide cap.
|
|
10
|
+
permissions: write
|
|
11
|
+
safe_outputs:
|
|
12
|
+
allow: [issue, comment, pr]
|
|
13
|
+
max: 25
|
|
6
14
|
nodes:
|
|
7
15
|
gather:
|
|
8
16
|
name: Gather Context
|
|
@@ -35,30 +43,14 @@ nodes:
|
|
|
35
43
|
- datadog
|
|
36
44
|
- betterstack
|
|
37
45
|
- linear
|
|
38
|
-
# Structural enforcement of the read-only scope above:
|
|
39
|
-
#
|
|
40
|
-
#
|
|
41
|
-
# Driving incident: the 2026-06-08
|
|
42
|
-
# run, where gather created Linear
|
|
43
|
-
# #101/#102 from inside this node and
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
- linear_create_issue
|
|
47
|
-
- linear_add_comment
|
|
48
|
-
- linear_update_issue
|
|
49
|
-
- github_create_issue
|
|
50
|
-
- github_add_comment
|
|
51
|
-
- github_create_pr
|
|
52
|
-
# Same incident: gather authored code changes mid-gather. Write/Edit are
|
|
53
|
-
# removed from the model context entirely. Bash stays available because
|
|
54
|
-
# read-side investigation legitimately uses it (git log, grep); blocking
|
|
55
|
-
# specific Bash invocations (git commit, gh pr create) needs the SDK's
|
|
56
|
-
# canUseTool callback and is tracked as follow-up work (see the implement
|
|
57
|
-
# node's note below).
|
|
58
|
-
disallowed_tools:
|
|
59
|
-
- Write
|
|
60
|
-
- Edit
|
|
61
|
-
- NotebookEdit
|
|
46
|
+
# Structural enforcement of the read-only scope above (#365): `read`
|
|
47
|
+
# registers only read skill tools, withholds external MCP servers, and
|
|
48
|
+
# removes every write-capable built-in (shell, file edits, subagents), on
|
|
49
|
+
# every harness. Driving incident: the 2026-06-08
|
|
50
|
+
# letsoffload/permit-service scheduled run, where gather created Linear
|
|
51
|
+
# issues OFF-2332/OFF-2333 and PRs #101/#102 from inside this node, and
|
|
52
|
+
# authored code changes, then died at the 50-turn cap.
|
|
53
|
+
permissions: read
|
|
62
54
|
# When gather still dies early (turn cap, SDK error), proceed with the
|
|
63
55
|
# partial context instead of failing the whole workflow: investigate has
|
|
64
56
|
# its own tools and can re-derive what gather missed. The 2026-06-08 run
|
|
@@ -140,16 +132,9 @@ nodes:
|
|
|
140
132
|
skills:
|
|
141
133
|
- github
|
|
142
134
|
- linear
|
|
143
|
-
# Structural enforcement of the scope boundaries above: the
|
|
144
|
-
#
|
|
145
|
-
|
|
146
|
-
deny:
|
|
147
|
-
- linear_create_issue
|
|
148
|
-
- linear_add_comment
|
|
149
|
-
- linear_update_issue
|
|
150
|
-
- github_create_issue
|
|
151
|
-
- github_add_comment
|
|
152
|
-
- github_create_pr
|
|
135
|
+
# Structural enforcement of the scope boundaries above (#365): the node
|
|
136
|
+
# is read-only, so no write tool or write-capable built-in reaches it.
|
|
137
|
+
permissions: read
|
|
153
138
|
eval:
|
|
154
139
|
# The novelty check REQUIRES searching the issue tracker. If the node finishes
|
|
155
140
|
# with 0 search tool calls, it means the agent skipped the novelty check entirely
|
|
@@ -225,6 +210,14 @@ nodes:
|
|
|
225
210
|
Process ALL findings from the investigation. The findings array contains both novel and duplicate issues.
|
|
226
211
|
|
|
227
212
|
|
|
213
|
+
**How writes work here.** If you have the `emit_output` tool, you cannot write to the tracker directly:
|
|
214
|
+
request each new issue and each comment with `emit_output`, and sweny files them after this step, within
|
|
215
|
+
its limits. A requested issue has no identifier yet; sweny records it for the next steps. Without
|
|
216
|
+
`emit_output`, use the tracker's own tools (for example `linear_create_issue`, `github_create_issue`,
|
|
217
|
+
`linear_add_comment`, `github_add_comment`, or the configured tracker's MCP tools) and copy the
|
|
218
|
+
identifier they return.
|
|
219
|
+
|
|
220
|
+
|
|
228
221
|
**For each NOVEL finding** (is_duplicate = false):
|
|
229
222
|
|
|
230
223
|
1. **First, check if a prior triage run already created an issue for this exact bug.** Call
|
|
@@ -232,76 +225,86 @@ nodes:
|
|
|
232
225
|
If a matching issue already exists with the same root cause:
|
|
233
226
|
- Treat it as a duplicate: DO NOT create a new issue.
|
|
234
227
|
- Populate `issueIdentifier`, `issueTitle`, and `issueUrl` from the existing issue.
|
|
235
|
-
- Add a "+1" comment if appropriate
|
|
228
|
+
- Add a "+1" comment if appropriate.
|
|
236
229
|
- Set the `action` to `updated` in the `issues` array.
|
|
237
230
|
- This prevents duplicate tickets when the same alert fires multiple times.
|
|
238
231
|
|
|
239
|
-
2. If no matching issue exists,
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
or `create_pull_request` from ToolSearch. The eval check requires the specific tool
|
|
245
|
-
names listed here.
|
|
232
|
+
2. If no matching issue exists, file a new one with a clear, actionable title (type `issue`). Do NOT
|
|
233
|
+
synthesize an identifier from an alert ID, commit SHA, or your own imagination: a new issue's
|
|
234
|
+
identifier comes only from the tracker. Set `dedupe_key` to a short stable fingerprint of the root
|
|
235
|
+
cause, so two findings with the same cause are filed once. Set the `action` to `requested` (or
|
|
236
|
+
`created` when you filed it with a tracker tool and have its identifier).
|
|
246
237
|
|
|
247
238
|
3. Include: root cause, severity, affected services, reproduction steps, and recommended fix.
|
|
248
239
|
|
|
249
240
|
4. Apply the `sweny`, `agent`, and `triage` labels. For Linear: call `linear_list_labels` to find the
|
|
250
|
-
IDs for labels named `sweny`, `agent`, and `triage`,
|
|
251
|
-
|
|
252
|
-
|
|
241
|
+
IDs for labels named `sweny`, `agent`, and `triage`, and pass those IDs as the labels (skip any that
|
|
242
|
+
don't exist in the team; don't invent IDs). For Linear, the target is the team ID (`linear_list_teams`).
|
|
243
|
+
For GitHub: labels `["sweny", "agent", "triage"]`.
|
|
253
244
|
|
|
254
245
|
5. Link to relevant commits, PRs, or existing issues.
|
|
255
246
|
|
|
256
|
-
6.
|
|
257
|
-
|
|
258
|
-
|
|
247
|
+
6. When you know the identifier (an existing issue, or one a tracker tool returned), copy it verbatim
|
|
248
|
+
into `issueIdentifier`. It must match `^[A-Z][A-Z0-9]*-\d+$` (e.g. `OFF-1234`); do not prefix it with
|
|
249
|
+
anything else. Leave `issueIdentifier` unset for an issue you only requested.
|
|
259
250
|
|
|
260
251
|
|
|
261
252
|
**For each DUPLICATE finding** (is_duplicate = true):
|
|
262
253
|
|
|
263
254
|
1. Find the existing issue (check duplicate_of field).
|
|
264
255
|
|
|
265
|
-
2. Check the issue's comments
|
|
266
|
-
24 hours, skip adding another comment.
|
|
256
|
+
2. Check the issue's comments. If the most recent comment is already from SWEny (contains "+1") within
|
|
257
|
+
the last 24 hours, skip adding another comment.
|
|
267
258
|
|
|
268
|
-
3. Otherwise add a SHORT comment
|
|
269
|
-
2 lines. No markdown headers, no emoji,
|
|
259
|
+
3. Otherwise add a SHORT comment (type `comment`, `number` = the issue ID or number): "+1 seen again
|
|
260
|
+
{UTC timestamp}. {one sentence of new context}." (Keep it under 2 lines. No markdown headers, no emoji,
|
|
261
|
+
no formatting.)
|
|
270
262
|
|
|
271
|
-
4. If the existing issue is closed
|
|
263
|
+
4. If the existing issue is closed or done: reopen it when you have a tool that can; otherwise say in
|
|
264
|
+
the comment that it is closed and was seen again.
|
|
272
265
|
|
|
273
266
|
|
|
274
267
|
If context.issueTemplate is provided, use it as the format for new issue bodies. Otherwise use a clear structure
|
|
275
268
|
with: Summary, Root Cause, Impact, Steps to Reproduce, and Recommended Fix.
|
|
276
269
|
|
|
277
270
|
|
|
278
|
-
Use the issue tracker specified in context (e.g. Linear, Jira, or GitHub Issues)
|
|
279
|
-
different tracker. Output the created
|
|
271
|
+
Use the issue tracker specified in context (e.g. Linear, Jira, or GitHub Issues). Do NOT fall back to a
|
|
272
|
+
different tracker. Output the issues you requested, created, or updated.
|
|
280
273
|
|
|
281
274
|
|
|
282
|
-
**IMPORTANT
|
|
275
|
+
**IMPORTANT: scope boundaries for this node:**
|
|
283
276
|
|
|
284
277
|
- DO NOT create branches, commits, or pull requests. The `implement` and `create_pr` nodes handle that.
|
|
285
278
|
|
|
286
|
-
- DO NOT call `create_pull_request`, `github_create_pr`, or any PR/branch tools.
|
|
287
|
-
|
|
288
279
|
- Your job is issue creation and duplicate management ONLY.
|
|
289
280
|
skills:
|
|
290
281
|
- linear
|
|
291
282
|
- github
|
|
292
|
-
#
|
|
283
|
+
# #365: this node reads and decides; it never holds a tracker write.
|
|
284
|
+
# Issues and +1 comments are declared outputs: sweny applies them after
|
|
285
|
+
# the node succeeds (and after its eval), via the configured tracker
|
|
286
|
+
# skill, capped per run and deduped. The node is read-only by default
|
|
287
|
+
# because it declares outputs. The next steps read the new issue's
|
|
288
|
+
# identifier from `context.create_issue.safe_outputs`.
|
|
289
|
+
outputs:
|
|
290
|
+
- type: issue
|
|
291
|
+
max: 10
|
|
292
|
+
- type: comment
|
|
293
|
+
max: 10
|
|
294
|
+
# Legacy runs (a tracker with no safe-output skill, see
|
|
295
|
+
# cli/builtin-workflows.ts) still never open PRs from here.
|
|
293
296
|
tools:
|
|
294
297
|
deny:
|
|
295
298
|
- github_create_pr
|
|
296
299
|
eval:
|
|
297
|
-
# Require a real issue-tracker
|
|
298
|
-
#
|
|
299
|
-
#
|
|
300
|
-
# the +1 path for duplicates.
|
|
300
|
+
# Require a real issue-tracker action: a search (the duplicate check) or
|
|
301
|
+
# a requested write. emit_output covers safe outputs; the tracker tool
|
|
302
|
+
# names cover a legacy run that writes directly.
|
|
301
303
|
- name: issue_tracker_tool_was_called
|
|
302
304
|
kind: function
|
|
303
305
|
rule:
|
|
304
306
|
any_tool_called:
|
|
307
|
+
- emit_output
|
|
305
308
|
- linear_create_issue
|
|
306
309
|
- github_create_issue
|
|
307
310
|
- linear_search_issues
|
|
@@ -315,21 +318,21 @@ nodes:
|
|
|
315
318
|
type: string
|
|
316
319
|
pattern: '^[A-Z][A-Z0-9]*-\d+$'
|
|
317
320
|
description: >-
|
|
318
|
-
Primary issue identifier (e.g. OFF-1234)
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
321
|
+
Primary issue identifier (e.g. OFF-1234) when known in this step: an existing issue the
|
|
322
|
+
duplicate check matched, or one a tracker tool returned. Unset for an issue only requested
|
|
323
|
+
through emit_output; sweny records its identifier in safe_outputs. Never invented from a
|
|
324
|
+
Sentry short-ID or commit SHA.
|
|
322
325
|
issueTitle:
|
|
323
326
|
type: string
|
|
324
|
-
description: Title of the primary issue
|
|
327
|
+
description: Title of the primary issue
|
|
325
328
|
issueUrl:
|
|
326
329
|
type: string
|
|
327
330
|
pattern: "^https?://"
|
|
328
|
-
description: URL of the primary issue
|
|
331
|
+
description: URL of the primary issue, when known in this step
|
|
329
332
|
issues:
|
|
330
333
|
type: array
|
|
331
334
|
minItems: 1
|
|
332
|
-
description: All issues created or updated during this step
|
|
335
|
+
description: All issues requested, created, or updated during this step
|
|
333
336
|
items:
|
|
334
337
|
type: object
|
|
335
338
|
properties:
|
|
@@ -342,23 +345,21 @@ nodes:
|
|
|
342
345
|
action:
|
|
343
346
|
type: string
|
|
344
347
|
enum:
|
|
348
|
+
- requested
|
|
345
349
|
- created
|
|
346
350
|
- updated
|
|
347
351
|
- reopened
|
|
348
352
|
required:
|
|
349
|
-
- identifier
|
|
350
353
|
- action
|
|
351
354
|
required:
|
|
352
|
-
- issueIdentifier
|
|
353
355
|
- issueTitle
|
|
354
|
-
- issueUrl
|
|
355
356
|
- issues
|
|
356
357
|
retry:
|
|
357
358
|
max: 1
|
|
358
359
|
instruction:
|
|
359
360
|
auto: true
|
|
360
361
|
skip:
|
|
361
|
-
name: Skip
|
|
362
|
+
name: Skip - All Duplicates or Low Priority
|
|
362
363
|
instruction: >-
|
|
363
364
|
Every finding from the investigation was either a duplicate or low-priority. No new issues need to be created.
|
|
364
365
|
|
|
@@ -367,32 +368,38 @@ nodes:
|
|
|
367
368
|
|
|
368
369
|
1. Find the existing issue (check duplicate_of field).
|
|
369
370
|
|
|
370
|
-
2. Check the issue's comments
|
|
371
|
-
24 hours, skip adding another comment.
|
|
371
|
+
2. Check the issue's comments. If the most recent comment is already from SWEny (contains "+1") within
|
|
372
|
+
the last 24 hours, skip adding another comment.
|
|
372
373
|
|
|
373
|
-
3. Otherwise add a SHORT comment
|
|
374
|
-
|
|
374
|
+
3. Otherwise add a SHORT comment (with `emit_output` type `comment` when you have it, `number` = the
|
|
375
|
+
issue ID or number): "+1 seen again {UTC timestamp}. {one sentence of new context}." (Keep it under 2
|
|
376
|
+
lines. No markdown headers, no emoji, no formatting.)
|
|
375
377
|
|
|
376
|
-
4. If the issue is closed
|
|
378
|
+
4. If the issue is closed or done: reopen it when you have a tool that can; otherwise say in the comment
|
|
379
|
+
that it is closed and was seen again.
|
|
377
380
|
|
|
378
381
|
|
|
379
382
|
For **low priority** findings, log a brief note about why they were skipped.
|
|
380
383
|
skills:
|
|
381
384
|
- linear
|
|
382
385
|
- github
|
|
383
|
-
#
|
|
384
|
-
#
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
- github_create_issue
|
|
389
|
-
- github_create_pr
|
|
386
|
+
# #365: comments on existing issues only, as a declared output. Read-only
|
|
387
|
+
# otherwise: it never creates issues or PRs.
|
|
388
|
+
outputs:
|
|
389
|
+
- type: comment
|
|
390
|
+
max: 10
|
|
390
391
|
implement:
|
|
391
392
|
name: Implement Fix
|
|
392
393
|
instruction: |-
|
|
393
394
|
Implement the fix identified during investigation, plus the tests that pin
|
|
394
|
-
it as a regression guard. The issue
|
|
395
|
-
context
|
|
395
|
+
it as a regression guard. The issue from the previous step is in your
|
|
396
|
+
context. Use its identifier for branch naming and commit messages.
|
|
397
|
+
|
|
398
|
+
**The issue identifier** (ISSUE_ID below): the `ref` of the `issue` entry
|
|
399
|
+
with status `applied` in `context.create_issue.safe_outputs` (the issue
|
|
400
|
+
sweny filed after the previous step), else
|
|
401
|
+
`context.create_issue.issueIdentifier` (an existing issue the previous
|
|
402
|
+
step matched, or one it filed directly).
|
|
396
403
|
|
|
397
404
|
## Quality bar (non-negotiable)
|
|
398
405
|
|
|
@@ -425,12 +432,18 @@ nodes:
|
|
|
425
432
|
|
|
426
433
|
## Steps
|
|
427
434
|
|
|
428
|
-
|
|
435
|
+
0. **Precondition: staged preview.** If the `issue` entry in
|
|
436
|
+
`context.create_issue.safe_outputs` has status `staged`, this run is a
|
|
437
|
+
preview (`--stage`) and no issue exists. STOP before touching the
|
|
438
|
+
checkout. Output `test_status: "skipped"`, `skipped_reason: "staged"`,
|
|
439
|
+
empty file lists, `branch: ""`, `commit_sha: ""`.
|
|
440
|
+
|
|
441
|
+
0a. **Precondition: verify ISSUE_ID is well-formed.**
|
|
429
442
|
The identifier MUST match `^[A-Z][A-Z0-9]*-\d+$` (e.g. `OFF-1234`). If it
|
|
430
443
|
is missing, empty, or matches a Sentry short-ID / slug / any other shape,
|
|
431
|
-
STOP immediately
|
|
444
|
+
STOP immediately. Do NOT invent a branch name from the Sentry event,
|
|
432
445
|
commit SHA, or alert payload. Return a failed status with a clear message
|
|
433
|
-
instead;
|
|
446
|
+
instead; a human will pick it up.
|
|
434
447
|
|
|
435
448
|
0b. **Precondition — check for an existing open PR for this issue.** Call
|
|
436
449
|
`github_search_issues` (which hits GitHub's `/search/issues` endpoint
|
|
@@ -466,12 +479,12 @@ nodes:
|
|
|
466
479
|
|
|
467
480
|
1. Create a feature branch from the base branch (check context for
|
|
468
481
|
baseBranch, default `main`). **Branch name MUST include the issue
|
|
469
|
-
identifier** exactly as
|
|
482
|
+
identifier** exactly as ISSUE_ID above.
|
|
470
483
|
Format: lowercase the identifier and use it as a prefix, e.g.
|
|
471
484
|
`off-1234-fix-null-check`. If the repository uses a different branch
|
|
472
485
|
convention (check context.branchPattern or the rules/CLAUDE.md for a
|
|
473
486
|
regex), follow that — but the identifier piece MUST still come from
|
|
474
|
-
|
|
487
|
+
ISSUE_ID, never from a Sentry short-ID.
|
|
475
488
|
|
|
476
489
|
2. Read the relevant source files to understand the current code AND read
|
|
477
490
|
the nearest existing test file (e.g. `foo.service.spec.ts` next to
|
|
@@ -498,8 +511,8 @@ nodes:
|
|
|
498
511
|
## Scope boundary — do NOT open the PR here
|
|
499
512
|
|
|
500
513
|
Stop after the commit. Do NOT push the branch, do NOT run `gh pr create`,
|
|
501
|
-
do NOT call any PR-creation tool. The dedicated `create_pr` node
|
|
502
|
-
|
|
514
|
+
do NOT call any PR-creation tool. The dedicated `create_pr` node pushes the
|
|
515
|
+
branch and requests the PR. Opening it from this node bypasses the workflow's
|
|
503
516
|
eval gate and triggers a self-close-and-recreate workaround (PR opened via
|
|
504
517
|
shell, then `github_create_pr` returns 422 "already exists" against the same
|
|
505
518
|
branch, then the agent closes the first PR to satisfy the eval). The
|
|
@@ -539,24 +552,24 @@ nodes:
|
|
|
539
552
|
explain why — do not force a bad fix.
|
|
540
553
|
skills:
|
|
541
554
|
- github
|
|
542
|
-
#
|
|
543
|
-
#
|
|
544
|
-
#
|
|
545
|
-
#
|
|
546
|
-
#
|
|
547
|
-
#
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
# Structural enforcement of the "do NOT open the PR here" boundary: the
|
|
555
|
-
# PR tool is not registered for this node. The dedicated create_pr node
|
|
556
|
-
# is the only place github_create_pr exists.
|
|
555
|
+
# A write node on purpose (#365): the code change itself. It edits files
|
|
556
|
+
# in the checkout, runs the tests, and commits, which needs file edits and
|
|
557
|
+
# a shell. It does not browse the web (`deny: [net]`, portable across
|
|
558
|
+
# harnesses). Restricting *which* shell commands run (e.g. blocking
|
|
559
|
+
# `gh pr create` / `git push`) needs a per-command policy and is follow-up
|
|
560
|
+
# work.
|
|
561
|
+
permissions:
|
|
562
|
+
access: write
|
|
563
|
+
deny: [net]
|
|
564
|
+
# Structural enforcement of the "do NOT open the PR here" boundary: no
|
|
565
|
+
# GitHub write tool is registered for this node. The PR is create_pr's
|
|
566
|
+
# declared output.
|
|
557
567
|
tools:
|
|
558
568
|
deny:
|
|
559
569
|
- github_create_pr
|
|
570
|
+
- github_create_issue
|
|
571
|
+
- github_add_comment
|
|
572
|
+
- github_add_labels
|
|
560
573
|
output:
|
|
561
574
|
type: object
|
|
562
575
|
properties:
|
|
@@ -601,18 +614,18 @@ nodes:
|
|
|
601
614
|
- `not-run` — tests exist but the environment couldn't
|
|
602
615
|
execute them. Explain in `test_notes`. Retry will fire.
|
|
603
616
|
- `skipped` — the node short-circuited before running tests
|
|
604
|
-
because a precondition was not met
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
Downstream `create_pr` is bypassed and
|
|
609
|
-
routes to `notify`.
|
|
617
|
+
because a precondition was not met: `open-pr-exists` (Step
|
|
618
|
+
0b found an open PR with the issue identifier in its
|
|
619
|
+
title; `existing_pr_url` MUST be populated) or `staged`
|
|
620
|
+
(Step 0: a preview run filed no issue). `skipped_reason`
|
|
621
|
+
MUST be populated. Downstream `create_pr` is bypassed and
|
|
622
|
+
the workflow routes to `notify`.
|
|
610
623
|
skipped_reason:
|
|
611
624
|
type: string
|
|
612
625
|
description: |
|
|
613
626
|
Why the node short-circuited. Only set when `test_status` is
|
|
614
|
-
`skipped
|
|
615
|
-
enum: [open-pr-exists]
|
|
627
|
+
`skipped`: `open-pr-exists` (Step 0b) or `staged` (Step 0).
|
|
628
|
+
enum: [open-pr-exists, staged]
|
|
616
629
|
existing_pr_url:
|
|
617
630
|
type: string
|
|
618
631
|
description: |
|
|
@@ -668,10 +681,11 @@ nodes:
|
|
|
668
681
|
- If test_status is "no-framework": test_files_changed MAY be empty.
|
|
669
682
|
Pass vacuously.
|
|
670
683
|
- If test_status is "skipped": test_files_changed MAY be empty.
|
|
671
|
-
The node short-circuited before writing any code
|
|
672
|
-
|
|
673
|
-
`existing_pr_url` MUST be populated;
|
|
674
|
-
|
|
684
|
+
The node short-circuited before writing any code. When
|
|
685
|
+
skipped_reason is "open-pr-exists" (Step 0b found an open PR
|
|
686
|
+
for the issue), `existing_pr_url` MUST be populated; when it
|
|
687
|
+
is "staged" (a preview run), nothing else is required. If
|
|
688
|
+
skipped_reason is missing, return no.
|
|
675
689
|
- If test_status is "fail" or "not-run": this evaluator should not
|
|
676
690
|
run (the prior value evaluator catches that). Pass vacuously.
|
|
677
691
|
|
|
@@ -686,30 +700,29 @@ nodes:
|
|
|
686
700
|
# A failed PR must not stop the run: the only edge is an unconditional one to notify.
|
|
687
701
|
on_fail: continue
|
|
688
702
|
instruction: >-
|
|
689
|
-
Open a pull request for the fix. The issue
|
|
703
|
+
Open a pull request for the fix. The issue is in your context from the create_issue step; its identifier
|
|
704
|
+
(ISSUE_ID) is the `ref` of the applied `issue` entry in `context.create_issue.safe_outputs`, else
|
|
705
|
+
`context.create_issue.issueIdentifier`. The branch is `context.implement.branch`.
|
|
690
706
|
|
|
691
707
|
|
|
692
708
|
1. Push the branch to the remote.
|
|
693
709
|
|
|
694
|
-
2.
|
|
695
|
-
|
|
696
|
-
`github_create_pr`
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
node (or a prior run) already opened a PR for this branch and the tool
|
|
700
|
-
recovered it instead of failing on 422. Treat this as success and return the
|
|
701
|
-
PR's URL and number — do NOT close it and call `github_create_pr` again.
|
|
710
|
+
2. Request the PR: with `emit_output` (type `pr`, `head` = the branch, `base` = the base branch,
|
|
711
|
+
default `main`) when you have it; sweny opens it after this step and reuses an open PR for the same
|
|
712
|
+
branch instead of failing. Without `emit_output`, call `github_create_pr` (use this exact tool name,
|
|
713
|
+
not `create_pull_request` or any other variant from ToolSearch); if it returns `reused: true`, treat
|
|
714
|
+
it as success and do NOT close it and call again.
|
|
702
715
|
|
|
703
716
|
3. PR title MUST start with the issue identifier in brackets.
|
|
704
|
-
Format: `[
|
|
717
|
+
Format: `[ISSUE_ID] fix: {short description}`.
|
|
705
718
|
|
|
706
719
|
4. In the PR body, include: summary of the bug, what the fix does, and a link to the issue
|
|
707
|
-
(context.create_issue.issueUrl). If the
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
the issue to Done on merge.
|
|
720
|
+
(its `url` in `context.create_issue.safe_outputs`, else context.create_issue.issueUrl). If the
|
|
721
|
+
investigation found a Sentry issue, include "Fixes {sentryShortId}" in the PR body so Sentry
|
|
722
|
+
auto-resolves on merge. If the issue tracker is Linear, also include the line "Fixes ISSUE_ID"
|
|
723
|
+
(e.g. "Fixes OFF-1234") so Linear links the PR and moves the issue to Done on merge.
|
|
711
724
|
|
|
712
|
-
5.
|
|
725
|
+
5. Labels: `["sweny", "agent", "triage"]`.
|
|
713
726
|
|
|
714
727
|
|
|
715
728
|
If context.prTemplate is provided, use it as the format for the PR body. Otherwise use a clear structure with:
|
|
@@ -720,14 +733,29 @@ nodes:
|
|
|
720
733
|
sweny:run_id:{context.cloudRunId} -->
|
|
721
734
|
|
|
722
735
|
|
|
723
|
-
Return the PR URL and number.
|
|
736
|
+
Return the branch and the PR title you requested (and the PR URL and number when a tool returned them).
|
|
724
737
|
skills:
|
|
725
738
|
- github
|
|
739
|
+
# A write node on purpose (#365): pushing the branch ships the code change
|
|
740
|
+
# and needs git in a shell. The PR itself is a declared output, so the
|
|
741
|
+
# agent never holds the PR write; no GitHub write tool is registered here.
|
|
742
|
+
permissions: write
|
|
743
|
+
outputs:
|
|
744
|
+
- type: pr
|
|
745
|
+
max: 1
|
|
746
|
+
labels: [sweny, agent, triage]
|
|
747
|
+
tools:
|
|
748
|
+
deny:
|
|
749
|
+
- github_create_pr
|
|
750
|
+
- github_create_issue
|
|
751
|
+
- github_add_comment
|
|
752
|
+
- github_add_labels
|
|
726
753
|
eval:
|
|
727
754
|
- name: pr_was_created
|
|
728
755
|
kind: function
|
|
729
756
|
rule:
|
|
730
757
|
any_tool_called:
|
|
758
|
+
- emit_output
|
|
731
759
|
- github_create_pr
|
|
732
760
|
retry:
|
|
733
761
|
max: 1
|
|
@@ -739,8 +767,12 @@ nodes:
|
|
|
739
767
|
Send a notification summarizing the triage result:
|
|
740
768
|
|
|
741
769
|
1. Include: alert summary, severity, root cause (1-2 sentences), and links to any created issues or PRs.
|
|
770
|
+
Issues and PRs sweny filed are in `safe_outputs` of the create_issue, skip and create_pr steps
|
|
771
|
+
(`ref` and `url` of each `applied` entry).
|
|
742
772
|
2. For critical/high severity, make the notification urgent.
|
|
743
773
|
3. For medium/low, a standard notification is fine.
|
|
774
|
+
4. If any `safe_outputs` entry has status `staged`, this run is a preview: send nothing, and put the
|
|
775
|
+
notification you would have sent in your summary.
|
|
744
776
|
|
|
745
777
|
Use whichever notification channel is available to you.
|
|
746
778
|
skills:
|
|
@@ -765,7 +797,7 @@ edges:
|
|
|
765
797
|
to: notify
|
|
766
798
|
- from: implement
|
|
767
799
|
to: notify
|
|
768
|
-
when: implement.test_status is "skipped" (Step 0b found an open PR already exists for the issue identifier)
|
|
800
|
+
when: implement.test_status is "skipped" (Step 0b found an open PR already exists for the issue identifier, or Step 0 found a staged preview)
|
|
769
801
|
- from: implement
|
|
770
802
|
to: create_pr
|
|
771
803
|
when: implement.test_status is "pass" or "no-framework" (no existing PR; fix was implemented or there is no test framework)
|