@plainconceptsplatform/workflows 1.5.0 → 1.6.10
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/route-processing.js +9 -2
- package/dist/workflow-catalog.js +1 -1
- package/loops/actions/apply-agent-output/action.yml +5 -0
- package/loops/actions/classify-route/classify-route.sh +34 -13
- package/loops/actions/decide-agent-retry/action.yml +31 -3
- package/loops/actions/decide-agent-retry/classify-failure.sh +50 -0
- package/loops/actions/housekeeping/action.yml +20 -0
- package/loops/actions/identify-gate-subject/action.yml +52 -17
- package/loops/actions/merge-train/action.yml +71 -0
- package/loops/actions/merge-train/merge-train.sh +495 -0
- package/loops/actions/push-agent-branch/action.yml +73 -45
- package/loops/actions/verify-route-matrix/verify-route-matrix.sh +290 -84
- package/loops/docs/diagrams.md +55 -13
- package/loops/scripts/compile-agent-workflows.mjs +20 -3
- package/loops/templates/ci/app-ci-dotnet-next.yml +13 -14
- package/loops/templates/ci/app-ci-node-monorepo.yml +13 -14
- package/loops/workflows/agent-implement.md +77 -32
- package/loops/workflows/agent-merge-gate.md +90 -62
- package/loops/workflows/agent-refine.md +9 -0
- package/loops/workflows/work-router.yml +285 -471
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# Managed by @plainconceptsplatform/workflows. Source: loops/workflows/agent-merge-gate.md. Update with `workflows update --force`; consumer edits may be overwritten.
|
|
3
3
|
env:
|
|
4
4
|
VERIFY_COMMANDS: ""
|
|
5
|
-
REPO_RULES: "Review the selected
|
|
5
|
+
REPO_RULES: "Review the selected pull request for defects and report what you verified. Do not decide the outcome: the workflow computes it from your report and from facts it measured before you ran."
|
|
6
6
|
# Where to look first, not what to escalate on. This list used to be the check that decided
|
|
7
7
|
# whether a machine merged without a human, and it decided by category: the prompt told the
|
|
8
8
|
# agent that a match "is not a defect, it is a reason this pull request needs a person". In a
|
|
@@ -13,34 +13,36 @@ env:
|
|
|
13
13
|
# One line: gh-aw joins a multi-line env value onto a single line when it compiles the lock.
|
|
14
14
|
RISK_INDICATORS: "Any diff touching authentication, authorization or session handling. Any change to a calculation or pricing engine, or to code handling money. Any database migration, or a change to an entity or schema. Any change to an audit or event log, or anything that could break its continuity. Any change to a public API contract or a shared library other repositories consume."
|
|
15
15
|
# Paths a bot may change but never merge on its own: an extended regular expression matched
|
|
16
|
-
# against every changed path in the pull request.
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
#
|
|
21
|
-
|
|
16
|
+
# against every changed path in the pull request. A match holds the merge for a human; it does
|
|
17
|
+
# not stop the agent repairing failed CI on the same files.
|
|
18
|
+
#
|
|
19
|
+
# Only the automation itself. This list used to hold every dependency manifest, lockfile and
|
|
20
|
+
# dotted directory as well, and with a size threshold and an owner list as wide it parked most
|
|
21
|
+
# of a night's pull requests for a person who then merged them by hand, unread, on Monday:
|
|
22
|
+
# in Pliny-Bot 32 of 40 bot pull requests in two days. What stops a merge now is what is
|
|
23
|
+
# genuinely dangerous to merge unseen: the workflows, the secrets, and a change too big to
|
|
24
|
+
# review in one pass.
|
|
25
|
+
PROTECTED_PATHS: '^\.github/'
|
|
22
26
|
# Paths whose change needs the person who owns them. A match forces OWNER REVIEW REQUIRED and
|
|
23
27
|
# sets blast radius high on its own, whatever the diff's size. CODEOWNERS names who is asked
|
|
24
|
-
# when the repository has that file; it is never a prerequisite
|
|
25
|
-
# one must still be able to protect its auth and its infrastructure.
|
|
28
|
+
# when the repository has that file; it is never a prerequisite.
|
|
26
29
|
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
29
|
-
#
|
|
30
|
-
|
|
31
|
-
# this one catches exactly three and they are the three that deserved an owner (a database
|
|
32
|
-
# migration, a change to the platform role definitions, and a downstream token service).
|
|
33
|
-
OWNER_PATHS: '(^|/)([Aa]uth|[Aa]uthn|[Aa]uthz|[Aa]uthentication|[Aa]uthorization|[Ii]dentity|[Ss]ecurity|[Ss]ecrets?|[Mm]igrations|[Ii]nfra|terraform|helm|k8s|deploy)(/|[A-Z][A-Za-z]*\.[a-z]+$)'
|
|
30
|
+
# Secrets: a `secrets` directory or file, an environment file, a key or a certificate. Code
|
|
31
|
+
# that handles secrets (a SecretMasker.cs) is not a secret; the review pass reads it like any
|
|
32
|
+
# other change.
|
|
33
|
+
OWNER_PATHS: '(^|/)([Ss]ecrets?(/|\.[A-Za-z0-9]+$)|\.env(\.[A-Za-z0-9_-]+)?$|[^/]+\.(pem|pfx|p12|key)$)'
|
|
34
34
|
# Paths worth a second look that do not, alone, need a person. A match raises the floor to
|
|
35
35
|
# medium, and medium with acceptable recoverability still auto-merges. This is the line that
|
|
36
|
-
# separates "look here" from "stop here",
|
|
37
|
-
|
|
38
|
-
#
|
|
39
|
-
|
|
40
|
-
#
|
|
41
|
-
#
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
# separates "look here" from "stop here". Auth, identity, security, migrations and
|
|
37
|
+
# infrastructure used to stop a merge from here; they are the review pass's to look at now, and
|
|
38
|
+
# a migration that rewrites data still parks through a `low` recoverability the agent evidences.
|
|
39
|
+
SENSITIVE_PATHS: '(^|/)([Dd]omain|entities|[Cc]ontracts)/|(^|/)([Aa]uth|[Aa]uthn|[Aa]uthz|[Aa]uthentication|[Aa]uthorization|[Ii]dentity|[Ss]ecurity|[Mm]igrations|[Ii]nfra|terraform|helm|k8s|deploy)(/|[A-Z][A-Za-z]*\.[a-z]+$)'
|
|
40
|
+
# Diff shape. Lines decide high: a change over ten thousand counted lines (tests, docs,
|
|
41
|
+
# translations and generated code excluded) is too big to merge unseen. It was a thousand, which
|
|
42
|
+
# is a normal feature once the tests are left out. A file count alone never decides, so the high
|
|
43
|
+
# file threshold is set out of reach; spread still raises medium.
|
|
44
|
+
BLAST_HIGH_FILES: "100000"
|
|
45
|
+
BLAST_HIGH_LINES: "10000"
|
|
44
46
|
BLAST_MEDIUM_FILES: "5"
|
|
45
47
|
BLAST_MEDIUM_LINES: "200"
|
|
46
48
|
# Paths that change no runtime behaviour: tests, docs, specs, translations and generated
|
|
@@ -80,14 +82,18 @@ env:
|
|
|
80
82
|
PARK_AT_UNUSABLE_OUTPUT: "2"
|
|
81
83
|
ISSUE_CONTEXT_PATH: /tmp/gh-aw/agent/issue-context.json
|
|
82
84
|
GH_AW_ALLOWED_BOTS: "platform-devbox[bot],github-actions[bot]"
|
|
85
|
+
# The bots whose pull requests the gate takes, in every spelling GitHub uses for one account.
|
|
86
|
+
# Any other author needs write access to the repository, as they would to push the branch.
|
|
87
|
+
TRUSTED_BOTS: "github-actions[bot] app/github-actions platform-devbox[bot]"
|
|
83
88
|
GIT_AUTHOR_NAME: "github-actions[bot]"
|
|
84
89
|
GIT_AUTHOR_EMAIL: "github-actions[bot]@users.noreply.github.com"
|
|
85
90
|
GIT_COMMITTER_NAME: "github-actions[bot]"
|
|
86
91
|
GIT_COMMITTER_EMAIL: "github-actions[bot]@users.noreply.github.com"
|
|
87
92
|
description: |
|
|
88
|
-
Decides what happens to a
|
|
89
|
-
risk assessment is clean, hand to a human when it is
|
|
90
|
-
|
|
93
|
+
Decides what happens to a pull request once CI has reported, whether the bot or a person with
|
|
94
|
+
write access opened it: merge when the risk assessment is clean, hand to a human when it is
|
|
95
|
+
genuinely dangerous, fix CI or a conflict when there is one. Called by the Work Router, one
|
|
96
|
+
pull request at a time by its merge train; does not trigger on public events.
|
|
91
97
|
|
|
92
98
|
In a stack, a child pull request (its base is the feature branch) merges into that feature
|
|
93
99
|
branch and its child issue closes with it; the root pull request is held for a person. The
|
|
@@ -154,6 +160,10 @@ jobs:
|
|
|
154
160
|
found: ${{ steps.subject.outputs.found }}
|
|
155
161
|
pr: ${{ steps.subject.outputs.pr }}
|
|
156
162
|
issue: ${{ steps.subject.outputs.issue }}
|
|
163
|
+
# Where verdicts, attempts and labels go: the issue, or the pull request when it closes none.
|
|
164
|
+
record: ${{ steps.subject.outputs.record }}
|
|
165
|
+
head_ref: ${{ steps.subject.outputs.head-ref }}
|
|
166
|
+
closes: ${{ steps.subject.outputs.closes }}
|
|
157
167
|
conclusion: ${{ steps.subject.outputs.conclusion }}
|
|
158
168
|
run-id: ${{ steps.subject.outputs.run-id }}
|
|
159
169
|
review_blocked: ${{ steps.review.outputs.review_blocked }}
|
|
@@ -173,7 +183,7 @@ jobs:
|
|
|
173
183
|
ci-conclusion: ${{ inputs.ci-conclusion }}
|
|
174
184
|
ci-run-id: ${{ inputs.ci-run-id }}
|
|
175
185
|
linked-issue: ${{ inputs.linked-issue }}
|
|
176
|
-
|
|
186
|
+
trusted-bots: ${{ env.TRUSTED_BOTS }}
|
|
177
187
|
- name: Block a pull request with requested changes
|
|
178
188
|
id: review
|
|
179
189
|
env:
|
|
@@ -310,8 +320,13 @@ jobs:
|
|
|
310
320
|
echo "check-diff is not installed (agent-harness 3.2.0 or later ships it), so comments and tests were not checked." >> "$GITHUB_STEP_SUMMARY"
|
|
311
321
|
exit 0
|
|
312
322
|
fi
|
|
313
|
-
|
|
314
|
-
|
|
323
|
+
# `|| code=$?`, not a bare `code=$?` on the next line. GitHub runs this under `bash -e`,
|
|
324
|
+
# and `set -uo pipefail` above does not undo it, so a check-diff that exited 1 (the
|
|
325
|
+
# `fail` this step exists to report) ended the step there: the job failed, the agent
|
|
326
|
+
# was skipped, and the pull request burned its whole attempt budget on a verdict that
|
|
327
|
+
# was never recorded (Pliny-Bot #686, six attempts in twenty minutes).
|
|
328
|
+
code=0
|
|
329
|
+
report=$(node .opencode/scripts/check-diff.mjs --base "$BASE" 2>&1) || code=$?
|
|
315
330
|
case "$code" in 0) result=pass ;; 1) result=fail ;; *) result=error ;; esac
|
|
316
331
|
delimiter="EOF_$(openssl rand -hex 8)"
|
|
317
332
|
{
|
|
@@ -354,14 +369,14 @@ jobs:
|
|
|
354
369
|
uses: ./.github/actions/remove-issue-labels
|
|
355
370
|
with:
|
|
356
371
|
token: ${{ steps.app-token.outputs.token }}
|
|
357
|
-
issue-number: ${{ needs.subject.outputs.
|
|
372
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
358
373
|
labels: ${{ env.WORKING_LABEL }}
|
|
359
374
|
- name: Flag owner review
|
|
360
375
|
if: needs.protected_changes.outputs.holds_review == 'true'
|
|
361
376
|
uses: ./.github/actions/add-issue-labels
|
|
362
377
|
with:
|
|
363
378
|
token: ${{ steps.app-token.outputs.token }}
|
|
364
|
-
issue-number: ${{ needs.subject.outputs.
|
|
379
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
365
380
|
labels: |-
|
|
366
381
|
${{ env.REVIEW_LABEL }}
|
|
367
382
|
${{ env.OWNER_REVIEW_LABEL }}
|
|
@@ -370,7 +385,7 @@ jobs:
|
|
|
370
385
|
uses: ./.github/actions/create-issue-comment
|
|
371
386
|
with:
|
|
372
387
|
token: ${{ steps.app-token.outputs.token }}
|
|
373
|
-
issue-number: ${{ needs.subject.outputs.
|
|
388
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
374
389
|
body: |
|
|
375
390
|
${{ env.GATE_MARKER }}
|
|
376
391
|
PR #${{ needs.subject.outputs.pr }} changes protected files and cannot be auto-merged.
|
|
@@ -439,7 +454,7 @@ jobs:
|
|
|
439
454
|
uses: ./.github/actions/create-issue-comment
|
|
440
455
|
with:
|
|
441
456
|
token: ${{ steps.app-token.outputs.token }}
|
|
442
|
-
issue-number: ${{ needs.subject.outputs.
|
|
457
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
443
458
|
body: |
|
|
444
459
|
Problems found in PR #${{ needs.subject.outputs.pr }}. ${{ steps.conflicts.outputs.has_conflicts == 'true' && 'Merge conflicts detected.' || 'CI failed.' }}
|
|
445
460
|
Bot is working on fixing it.
|
|
@@ -473,7 +488,7 @@ jobs:
|
|
|
473
488
|
uses: ./.github/actions/validate-merge-gate-output
|
|
474
489
|
with:
|
|
475
490
|
output-file: ${{ steps.output.outputs.output-file }}
|
|
476
|
-
issue-number: ${{ needs.subject.outputs.
|
|
491
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
477
492
|
ci-conclusion: ${{ needs.subject.outputs.conclusion }}
|
|
478
493
|
blast-level: ${{ needs.protected_changes.outputs.level }}
|
|
479
494
|
protected-hit: ${{ needs.protected_changes.outputs.requires_review }}
|
|
@@ -511,18 +526,23 @@ jobs:
|
|
|
511
526
|
token: ${{ steps.app-token.outputs.token }}
|
|
512
527
|
fetch-depth: 0
|
|
513
528
|
- name: Verify pull request closes the source issue
|
|
529
|
+
if: needs.subject.outputs.issue != ''
|
|
514
530
|
continue-on-error: true
|
|
515
531
|
uses: ./.github/actions/link-pr-to-issue
|
|
516
532
|
with:
|
|
517
533
|
token: ${{ steps.app-token.outputs.token }}
|
|
518
534
|
pr-number: ${{ needs.subject.outputs.pr }}
|
|
519
535
|
issue-number: ${{ needs.subject.outputs.issue }}
|
|
536
|
+
# The push goes to this pull request's branch or nowhere. A `[bot] ` title prefix used to be
|
|
537
|
+
# the guard, which a person's pull request does not carry; the branch the subject job read
|
|
538
|
+
# is the exact one, whoever opened it.
|
|
520
539
|
- name: Apply agent output
|
|
521
540
|
uses: ./.github/actions/apply-agent-output
|
|
522
541
|
with:
|
|
523
542
|
artifact-name: ${{ needs.activation.outputs.artifact_prefix }}agent
|
|
524
543
|
token: ${{ steps.app-token.outputs.token }}
|
|
525
544
|
push-to-branch: 'true'
|
|
545
|
+
expected-branch: ${{ needs.subject.outputs.head_ref }}
|
|
526
546
|
apply-labels: 'false'
|
|
527
547
|
# GITHUB_TOKEN on purpose: an App-token comment on a pull request is an issue_comment
|
|
528
548
|
# event, and GITHUB_TOKEN raises none. The full assessment lives on the issue, where the
|
|
@@ -558,7 +578,7 @@ jobs:
|
|
|
558
578
|
${{ needs.protected_changes.outputs.signals }}
|
|
559
579
|
```
|
|
560
580
|
|
|
561
|
-
Findings and verification on the linked issue:
|
|
581
|
+
${{ needs.subject.outputs.issue != '' && format('Findings and verification on the linked issue: #{0}.', needs.subject.outputs.issue) || 'Findings and verification are in the review comment above.' }} [View this workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
|
562
582
|
${{ env.EVIDENCE_BEFORE_REVIEW == 'true' && contains(fromJson('["human-review","owner-review"]'), needs.validate_output.outputs.outcome) && 'Screenshots of this head follow in their own comment if it carries a verification plan. Approving the pull request merges it.' || '' }}
|
|
563
583
|
- name: Merge approved pull request
|
|
564
584
|
if: needs.validate_output.outputs.outcome == 'auto-merge' && needs.subject.outputs.stack_root != 'true'
|
|
@@ -579,7 +599,7 @@ jobs:
|
|
|
579
599
|
uses: ./.github/actions/create-issue-comment
|
|
580
600
|
with:
|
|
581
601
|
token: ${{ steps.app-token.outputs.token }}
|
|
582
|
-
issue-number: ${{ needs.subject.outputs.
|
|
602
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
583
603
|
body: |
|
|
584
604
|
**Stack root held.** This pull request is the root of a stack: its children merge
|
|
585
605
|
into the feature branch, and it merges into ${{ github.event.repository.default_branch }} only when a person
|
|
@@ -589,7 +609,7 @@ jobs:
|
|
|
589
609
|
uses: ./.github/actions/remove-issue-labels
|
|
590
610
|
with:
|
|
591
611
|
token: ${{ steps.app-token.outputs.token }}
|
|
592
|
-
issue-number: ${{ needs.subject.outputs.
|
|
612
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
593
613
|
labels: ${{ env.WORKING_LABEL }}
|
|
594
614
|
# `review` goes on for all three parked dispositions, so every board query and every
|
|
595
615
|
# authorize-bot-work handoff that already reads it keeps working. The second label is what
|
|
@@ -599,7 +619,7 @@ jobs:
|
|
|
599
619
|
uses: ./.github/actions/add-issue-labels
|
|
600
620
|
with:
|
|
601
621
|
token: ${{ steps.app-token.outputs.token }}
|
|
602
|
-
issue-number: ${{ needs.subject.outputs.
|
|
622
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
603
623
|
labels: |-
|
|
604
624
|
${{ env.REVIEW_LABEL }}
|
|
605
625
|
${{ needs.validate_output.outputs.outcome == 'owner-review' && env.OWNER_REVIEW_LABEL || '' }}
|
|
@@ -631,7 +651,7 @@ jobs:
|
|
|
631
651
|
uses: ./.github/actions/remove-issue-labels
|
|
632
652
|
with:
|
|
633
653
|
token: ${{ steps.app-token.outputs.token }}
|
|
634
|
-
issue-number: ${{ needs.subject.outputs.
|
|
654
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
635
655
|
labels: ${{ env.WORKING_LABEL }}
|
|
636
656
|
# GitHub's closing keywords never fire when a PR merges into a branch other than the
|
|
637
657
|
# default, so a child PR landing on the feature branch leaves its issue open — and
|
|
@@ -641,7 +661,7 @@ jobs:
|
|
|
641
661
|
# and `gh issue close` on an already-closed issue is a harmless no-op, making the
|
|
642
662
|
# step safe to re-run.
|
|
643
663
|
- name: Close the child issue when the pull request landed on a feature branch
|
|
644
|
-
if: needs.validate_output.outputs.outcome == 'auto-merge' && needs.subject.outputs.pr_base != '' && needs.subject.outputs.pr_base != github.event.repository.default_branch
|
|
664
|
+
if: needs.validate_output.outputs.outcome == 'auto-merge' && needs.subject.outputs.issue != '' && needs.subject.outputs.pr_base != '' && needs.subject.outputs.pr_base != github.event.repository.default_branch
|
|
645
665
|
env:
|
|
646
666
|
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
647
667
|
REPO: ${{ github.repository }}
|
|
@@ -668,7 +688,7 @@ jobs:
|
|
|
668
688
|
uses: ./.github/actions/remove-issue-labels
|
|
669
689
|
with:
|
|
670
690
|
token: ${{ steps.app-token.outputs.token }}
|
|
671
|
-
issue-number: ${{ needs.subject.outputs.
|
|
691
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
672
692
|
labels: |
|
|
673
693
|
${{ env.IMPLEMENT_LABEL }}
|
|
674
694
|
${{ env.WORKING_LABEL }}
|
|
@@ -676,8 +696,12 @@ jobs:
|
|
|
676
696
|
${{ env.OWNER_REVIEW_LABEL }}
|
|
677
697
|
${{ env.BLOCKED_LABEL }}
|
|
678
698
|
${{ env.PR_PENDING_LABEL }}
|
|
699
|
+
# A conclude that dies (a push refused, a token rejected) is a failed attempt too. Without it
|
|
700
|
+
# here the run left no verdict and no attempt comment, which the merge train reads as a gate that
|
|
701
|
+
# did nothing and never offers the pull request again: Pliny-Bot #716 sat stranded that way after
|
|
702
|
+
# its repair was computed and then lost to a rejected git fetch in conclude.
|
|
679
703
|
incomplete:
|
|
680
|
-
needs: [subject, protected_changes, agent, safe_outputs, validate_output]
|
|
704
|
+
needs: [subject, protected_changes, agent, safe_outputs, validate_output, conclude]
|
|
681
705
|
if: >
|
|
682
706
|
always() &&
|
|
683
707
|
needs.subject.outputs.found == 'true' &&
|
|
@@ -685,7 +709,8 @@ jobs:
|
|
|
685
709
|
(
|
|
686
710
|
needs.agent.result != 'success' ||
|
|
687
711
|
needs.safe_outputs.result != 'success' ||
|
|
688
|
-
needs.validate_output.outputs.valid != 'true'
|
|
712
|
+
needs.validate_output.outputs.valid != 'true' ||
|
|
713
|
+
needs.conclude.result == 'failure'
|
|
689
714
|
)
|
|
690
715
|
runs-on: agents-arc
|
|
691
716
|
permissions:
|
|
@@ -745,18 +770,18 @@ jobs:
|
|
|
745
770
|
uses: ./.github/actions/create-issue-comment
|
|
746
771
|
with:
|
|
747
772
|
token: ${{ steps.app-token.outputs.token }}
|
|
748
|
-
issue-number: ${{ needs.subject.outputs.
|
|
773
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
749
774
|
body: |
|
|
750
775
|
${{ env.ATTEMPT_MARKER }}
|
|
751
776
|
Attempt ${{ inputs.attempts_so_far || '0' }} of ${{ env.MAX_ATTEMPTS }} on PR #${{ needs.subject.outputs.pr }} ended without an outcome.
|
|
752
|
-
This failure parks at ${{ steps.budget.outputs.threshold }}. The
|
|
777
|
+
This failure parks at ${{ steps.budget.outputs.threshold }}. The merge train will retry.
|
|
753
778
|
[View this workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
|
754
779
|
- name: Report the exhausted attempt budget
|
|
755
780
|
if: steps.budget.outputs.park == 'true' && steps.budget.outputs.kind == 'machine'
|
|
756
781
|
uses: ./.github/actions/create-issue-comment
|
|
757
782
|
with:
|
|
758
783
|
token: ${{ steps.app-token.outputs.token }}
|
|
759
|
-
issue-number: ${{ needs.subject.outputs.
|
|
784
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
760
785
|
body: |
|
|
761
786
|
${{ env.ATTEMPT_MARKER }}
|
|
762
787
|
Attempt ${{ inputs.attempts_so_far || '0' }} of ${{ steps.budget.outputs.threshold }} on PR #${{ needs.subject.outputs.pr }} ended without an outcome.
|
|
@@ -774,7 +799,7 @@ jobs:
|
|
|
774
799
|
uses: ./.github/actions/create-issue-comment
|
|
775
800
|
with:
|
|
776
801
|
token: ${{ steps.app-token.outputs.token }}
|
|
777
|
-
issue-number: ${{ needs.subject.outputs.
|
|
802
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
778
803
|
body: |
|
|
779
804
|
${{ env.GATE_MARKER }}
|
|
780
805
|
The agent finished on PR #${{ needs.subject.outputs.pr }} but its report could not be
|
|
@@ -794,7 +819,7 @@ jobs:
|
|
|
794
819
|
token: ${{ steps.app-token.outputs.token }}
|
|
795
820
|
issue-number: ${{ needs.subject.outputs.pr }}
|
|
796
821
|
body: |
|
|
797
|
-
The merge gate stopped on this pull request and handed it to a person (
|
|
822
|
+
The merge gate stopped on this pull request and handed it to a person${{ needs.subject.outputs.issue != '' && format(' (#{0})', needs.subject.outputs.issue) || '' }}.
|
|
798
823
|
${{ needs.validate_output.outputs.pushed == 'true' && 'The agent pushed a repair that was not applied because its report could not be read. The patch and bundle are in the `agent` artifact of the run below.' || '' }}
|
|
799
824
|
[View this workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
|
800
825
|
- name: Label the pull request for review
|
|
@@ -812,7 +837,7 @@ jobs:
|
|
|
812
837
|
uses: ./.github/actions/add-issue-labels
|
|
813
838
|
with:
|
|
814
839
|
token: ${{ steps.app-token.outputs.token }}
|
|
815
|
-
issue-number: ${{ needs.subject.outputs.
|
|
840
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
816
841
|
labels: |-
|
|
817
842
|
${{ env.REVIEW_LABEL }}
|
|
818
843
|
${{ steps.budget.outputs.kind == 'machine' && env.STALLED_LABEL || '' }}
|
|
@@ -822,7 +847,7 @@ jobs:
|
|
|
822
847
|
uses: ./.github/actions/remove-issue-labels
|
|
823
848
|
with:
|
|
824
849
|
token: ${{ steps.app-token.outputs.token }}
|
|
825
|
-
issue-number: ${{ needs.subject.outputs.
|
|
850
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
826
851
|
labels: ${{ env.WORKING_LABEL }}
|
|
827
852
|
|
|
828
853
|
agent:
|
|
@@ -892,7 +917,7 @@ steps:
|
|
|
892
917
|
uses: ./.github/actions/load-issue-context
|
|
893
918
|
with:
|
|
894
919
|
token: ${{ github.token }}
|
|
895
|
-
issue-number: ${{ needs.subject.outputs.
|
|
920
|
+
issue-number: ${{ needs.subject.outputs.record }}
|
|
896
921
|
output-path: ${{ env.ISSUE_CONTEXT_PATH }}
|
|
897
922
|
- name: Fetch the diff and any failing job logs
|
|
898
923
|
env:
|
|
@@ -934,9 +959,10 @@ safe-outputs:
|
|
|
934
959
|
# target "*" because these workers are dispatched, not triggered by the pull request:
|
|
935
960
|
# the default "triggering" target has no pull request in context and rejects the push
|
|
936
961
|
# with "requires pull request context", so the agent's fix is computed and discarded.
|
|
962
|
+
# No title prefix: the gate repairs pull requests people opened as well, and conclude pushes
|
|
963
|
+
# only to the branch of the pull request the subject job validated.
|
|
937
964
|
push-to-pull-request-branch:
|
|
938
965
|
target: "*"
|
|
939
|
-
required-title-prefix: "[bot] "
|
|
940
966
|
max-patch-size: 10240
|
|
941
967
|
# A failed bot PR may already contain protected files. Permit a verified repair push,
|
|
942
968
|
# but protected_changes still prevents the later green-CI cycle from auto-merging it.
|
|
@@ -955,13 +981,13 @@ safe-outputs:
|
|
|
955
981
|
timeout-minutes: 120
|
|
956
982
|
---
|
|
957
983
|
|
|
958
|
-
1. You are gating pull request **#${{ needs.subject.outputs.pr }}**, which closes
|
|
959
|
-
|
|
960
|
-
**${{ needs.subject.outputs.conclusion }}**.
|
|
984
|
+
1. You are gating pull request **#${{ needs.subject.outputs.pr }}**, which ${{ needs.subject.outputs.closes }}.
|
|
985
|
+
CI concluded **${{ needs.subject.outputs.conclusion }}**.
|
|
961
986
|
|
|
962
|
-
It has already been confirmed that this is an open pull request
|
|
963
|
-
|
|
964
|
-
|
|
987
|
+
It has already been confirmed that this is an open pull request from this repository, opened
|
|
988
|
+
by the bot or by someone with write access. Do not re-check any of that, and do not poll for
|
|
989
|
+
checks: the conclusion above is the answer. Who opened it changes nothing below: a person's
|
|
990
|
+
pull request is repaired, reviewed and merged by the same rules as the bot's.
|
|
965
991
|
|
|
966
992
|
You are on the pull request branch. Never rebase, reset, amend or otherwise rewrite
|
|
967
993
|
history: the workflow applies your commits as a bundle with a fast-forward-only push and
|
|
@@ -969,9 +995,11 @@ timeout-minutes: 120
|
|
|
969
995
|
`push_to_pull_request_branch` tool's own description recommends rebasing; in this
|
|
970
996
|
repository that advice is wrong. Merge, commit, and let the workflow push.
|
|
971
997
|
|
|
972
|
-
2. Read `${{ env.ISSUE_CONTEXT_PATH }}`. It contains the issue body and its discussion
|
|
998
|
+
2. Read `${{ env.ISSUE_CONTEXT_PATH }}`. It contains the issue body and its discussion, or, for
|
|
999
|
+
a pull request that closes no issue, the pull request's own description and discussion. The
|
|
973
1000
|
acceptance criteria there define what this implementation had to satisfy, and step 5c asks
|
|
974
|
-
you to check the diff against them.
|
|
1001
|
+
you to check the diff against them. A description with no stated criteria is checked against
|
|
1002
|
+
what it says the change does.
|
|
975
1003
|
|
|
976
1004
|
3. Branch on the conclusion.
|
|
977
1005
|
|
|
@@ -1225,7 +1253,7 @@ timeout-minutes: 120
|
|
|
1225
1253
|
your report and from the facts it measured, and a word it does not recognise parks the pull
|
|
1226
1254
|
request. Never merge with administrator privileges and never bypass a required check.
|
|
1227
1255
|
|
|
1228
|
-
8. Emit exactly one `add_comment` targeting
|
|
1256
|
+
8. Emit exactly one `add_comment` targeting item `${{ needs.subject.outputs.record }}`,
|
|
1229
1257
|
containing, in this order:
|
|
1230
1258
|
|
|
1231
1259
|
1. `${{ env.GATE_MARKER }}`
|
|
@@ -837,9 +837,11 @@ safe-outputs:
|
|
|
837
837
|
# was sent with an incorrect parameter shape (20 bytes, missing body) and was accepted
|
|
838
838
|
# with success by the bridge, consuming the 1-per-run quota". The prompt still says to
|
|
839
839
|
# send the body once.
|
|
840
|
+
# `title:` lets refine set an English title when the issue was written in another language.
|
|
840
841
|
update-issue:
|
|
841
842
|
target: "*"
|
|
842
843
|
max: 3
|
|
844
|
+
title:
|
|
843
845
|
add-comment:
|
|
844
846
|
# Split children. An oversized story becomes several implementable ones rather than
|
|
845
847
|
# one issue nobody can land; the cap stops a runaway decomposition.
|
|
@@ -976,6 +978,13 @@ timeout-minutes: 90
|
|
|
976
978
|
The visible line is for people and the marker is read by the workflow, which turns it into the
|
|
977
979
|
`sp-N` label. A body without the marker gets no estimate label at all.
|
|
978
980
|
|
|
981
|
+
**Everything you write is in English, whatever language the issue was written in.** Bodies,
|
|
982
|
+
child issues, comments and questions are English. When the title of the issue you are refining
|
|
983
|
+
is not English, put an English title in the same `update_issue` call as the body, as
|
|
984
|
+
`{"issue_number":N,"title":"...","body":"..."}`: it carries the same meaning, short, with no
|
|
985
|
+
language tag. People write issues in their own language, and everything the workflow produces
|
|
986
|
+
from them (pull requests, commits, the run history) is read by everyone else in English.
|
|
987
|
+
|
|
979
988
|
7. **One safe-output call per turn.** Never batch multiple safe-output calls into a single
|
|
980
989
|
message: `update_issue`, `create_issue` and `add_comment` each go in their own turn, with
|
|
981
990
|
nothing else in the message. The provider caps one response at a fixed size, and a batch of
|