@plainconceptsplatform/workflows 0.17.0 → 0.20.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/dist/catalog-installation.js +25 -13
- package/dist/stack-defaults.js +16 -16
- package/dist/worker-env.js +24 -21
- package/loops/actions/add-issue-labels/action.yml +50 -50
- package/loops/actions/agent-output.cjs +17 -17
- package/loops/actions/apply-agent-bundle/action.yml +24 -24
- package/loops/actions/apply-agent-comments/action.yml +42 -42
- package/loops/actions/apply-agent-labels/action.yml +55 -55
- package/loops/actions/apply-agent-output/action.yml +108 -108
- package/loops/actions/assess-blast-radius/action.yml +148 -0
- package/loops/actions/assess-blast-radius/assess-blast-radius.sh +138 -0
- package/loops/actions/classify-route/action.yml +100 -100
- package/loops/actions/cleanup-artifacts/action.yml +91 -91
- package/loops/actions/close-agent-issues/action.yml +43 -43
- package/loops/actions/create-agent-issues/action.yml +52 -52
- package/loops/actions/create-issue-comment/action.yml +29 -29
- package/loops/actions/download-agent-output/action.yml +53 -53
- package/loops/actions/housekeeping/action.yml +55 -2
- package/loops/actions/identify-gate-subject/action.yml +134 -122
- package/loops/actions/link-pr-to-issue/action.yml +40 -40
- package/loops/actions/list-open-issues/action.yml +33 -33
- package/loops/actions/load-issue-context/action.yml +45 -45
- package/loops/actions/merge-agent-pr/action.yml +49 -49
- package/loops/actions/push-agent-branch/action.yml +45 -45
- package/loops/actions/remove-issue-labels/action.yml +37 -37
- package/loops/actions/require-open-issue/action.yml +59 -0
- package/loops/actions/update-agent-issues/action.yml +58 -58
- package/loops/actions/validate-merge-gate-output/action.yml +62 -40
- package/loops/actions/validate-merge-gate-output/validate-merge-gate-output.sh +147 -31
- package/loops/actions/validate-refine-output/action.yml +48 -44
- package/loops/actions/validate-refine-output/validate-refine-output.sh +15 -4
- package/loops/actions/validate-review-output/action.yml +35 -35
- package/loops/actions/validate-triage-output/action.yml +36 -36
- package/loops/actions/verify-composite-actions/action.yml +9 -9
- package/loops/actions/verify-refine-output/action.yml +9 -9
- package/loops/actions/verify-refine-output/verify-refine-output.sh +6 -1
- package/loops/actions/verify-route-matrix/action.yml +9 -9
- package/loops/actions/verify-route-matrix/verify-gate-metrics.mjs +51 -0
- package/loops/actions/verify-route-matrix/verify-route-matrix.sh +630 -8
- package/loops/scripts/compile-agent-workflows.mjs +331 -331
- package/loops/templates/agentics/agentics-maintenance.yml +121 -121
- package/loops/templates/ci/app-ci-dotnet-next.yml +330 -330
- package/loops/templates/ci/app-ci-node-monorepo.yml +260 -260
- package/loops/templates/issues/bug_report.yml +109 -109
- package/loops/templates/issues/feature_request.yml +75 -75
- package/loops/templates/opencode/opencode.ci.json +55 -49
- package/loops/templates/opencode/opencode.ci.json.md +59 -49
- package/loops/templates/release/github-release.yml +30 -30
- package/loops/workflows/agent-apply-review.md +33 -3
- package/loops/workflows/agent-audit.md +36 -0
- package/loops/workflows/agent-implement.md +77 -5
- package/loops/workflows/agent-merge-gate.md +368 -148
- package/loops/workflows/agent-refine.md +93 -17
- package/loops/workflows/agent-release.md +4 -4
- package/loops/workflows/agent-triage.md +33 -1
- package/loops/workflows/authorize-bot-work.yml +105 -105
- package/loops/workflows/shared/opencode-ci.md +206 -206
- package/loops/workflows/shared/platform-defaults.md +19 -19
- package/loops/workflows/work-router.yml +25 -11
- package/package.json +2 -2
|
@@ -49,7 +49,37 @@ on:
|
|
|
49
49
|
|
|
50
50
|
# Rung 4. Router has classified the event; this job validates PR ownership and checks for
|
|
51
51
|
# substantive feedback. A custom job, not `on.steps`, because the prompt needs these values.
|
|
52
|
+
# The gate job that the top-level `if:` reads. gh-aw folds that `if:` into the generated
|
|
53
|
+
# activation job but gives activation no dependency on the job, so the reference resolves
|
|
54
|
+
# to '' and the clause is false -- the agent would never run. The package's own validator
|
|
55
|
+
# catches it after compilation; this is the line it asks for, the same one the merge gate
|
|
56
|
+
# uses for protected_changes.
|
|
57
|
+
needs: [still_open]
|
|
52
58
|
jobs:
|
|
59
|
+
# A route dispatched while the issue was open must not execute after it has been closed. The
|
|
60
|
+
# classifier can only see `github.event.issue.state`, which is the state when the event fired
|
|
61
|
+
# and is absent on a workflow_dispatch, and this fleet queues for a runner for ten minutes and
|
|
62
|
+
# more. Numa #659 was closed one second after a comment dispatched refine; the run reached
|
|
63
|
+
# `reserve` thirteen minutes later and refined a closed issue to completion. Read now, once,
|
|
64
|
+
# and gate both the reservation and the agent on it.
|
|
65
|
+
still_open:
|
|
66
|
+
runs-on: agents-arc
|
|
67
|
+
permissions:
|
|
68
|
+
contents: read
|
|
69
|
+
issues: read
|
|
70
|
+
outputs:
|
|
71
|
+
open: ${{ steps.state.outputs.open }}
|
|
72
|
+
steps:
|
|
73
|
+
- name: Checkout workflow actions
|
|
74
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
75
|
+
with:
|
|
76
|
+
persist-credentials: false
|
|
77
|
+
- name: Read the issue state
|
|
78
|
+
id: state
|
|
79
|
+
uses: ./.github/actions/require-open-issue
|
|
80
|
+
with:
|
|
81
|
+
token: ${{ github.token }}
|
|
82
|
+
issue-number: ${{ inputs.issue-number }}
|
|
53
83
|
subject:
|
|
54
84
|
runs-on: agents-arc
|
|
55
85
|
permissions:
|
|
@@ -118,8 +148,8 @@ jobs:
|
|
|
118
148
|
echo "PR #$PR has $unresolved unresolved thread(s)"
|
|
119
149
|
|
|
120
150
|
reserve:
|
|
121
|
-
needs: subject
|
|
122
|
-
if: needs.subject.outputs.found == 'true' && needs.subject.outputs.issue != ''
|
|
151
|
+
needs: [subject, still_open]
|
|
152
|
+
if: needs.subject.outputs.found == 'true' && needs.subject.outputs.issue != '' && needs.still_open.outputs.open == 'true'
|
|
123
153
|
runs-on: agents-arc
|
|
124
154
|
permissions:
|
|
125
155
|
contents: read
|
|
@@ -290,7 +320,7 @@ jobs:
|
|
|
290
320
|
${{ env.INCOMPLETE_COMMENT }}
|
|
291
321
|
[View this workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
|
292
322
|
|
|
293
|
-
if: needs.subject.outputs.found == 'true'
|
|
323
|
+
if: needs.subject.outputs.found == 'true' && needs.still_open.outputs.open == 'true'
|
|
294
324
|
|
|
295
325
|
runs-on: agents-arc
|
|
296
326
|
runs-on-slim: agents-arc
|
|
@@ -119,6 +119,42 @@ jobs:
|
|
|
119
119
|
bug
|
|
120
120
|
refine
|
|
121
121
|
|
|
122
|
+
# An audit that produced nothing reported success. The whole run -- a full agent, its tokens,
|
|
123
|
+
# its half hour -- ended with `conclude` skipped, because that job requires a processed item,
|
|
124
|
+
# and a skipped job leaves the run green. Numa's audit on 2026-09-10 did exactly that:
|
|
125
|
+
# `agent_output.json` 24 bytes, `safe-output-items.jsonl` empty, every job success, no report
|
|
126
|
+
# filed and nothing anywhere saying so. The next scheduled audit would have looked identical.
|
|
127
|
+
#
|
|
128
|
+
# This fires when the agent succeeded and the safe-outputs handler processed nothing at all.
|
|
129
|
+
#
|
|
130
|
+
# Step 6 of the prompt gives a clean codebase its own outcome -- call `noop` and stop -- and
|
|
131
|
+
# that outcome must not be reported as a failure. `noop` is a registered safe output here
|
|
132
|
+
# (`noop: max 1`), so the handler receives it as a message and the processed count is not zero,
|
|
133
|
+
# which keeps a deliberately empty audit out of this branch. That is read from the handler
|
|
134
|
+
# configuration rather than observed in a run: no audit in these repositories has yet emitted a
|
|
135
|
+
# noop. The direct signal, `noop_message`, belongs to gh-aw's `conclusion` job, and that job
|
|
136
|
+
# depends on every custom job here, so naming it is a dependency cycle and the worker will not
|
|
137
|
+
# compile -- the first version of this job was rejected for exactly that.
|
|
138
|
+
#
|
|
139
|
+
# If a genuinely clean audit ever fails here, that is the assumption breaking, and the fix is to
|
|
140
|
+
# carry the noop through a job this one can depend on rather than to widen the condition.
|
|
141
|
+
empty_run:
|
|
142
|
+
needs: [agent, safe_outputs]
|
|
143
|
+
if: >
|
|
144
|
+
needs.agent.result == 'success' &&
|
|
145
|
+
needs.safe_outputs.outputs.process_safe_outputs_processed_count == '0'
|
|
146
|
+
runs-on: agents-arc
|
|
147
|
+
permissions:
|
|
148
|
+
contents: read
|
|
149
|
+
steps:
|
|
150
|
+
- name: Report an audit that produced no outcome
|
|
151
|
+
env:
|
|
152
|
+
RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
|
153
|
+
run: |
|
|
154
|
+
set -euo pipefail
|
|
155
|
+
echo "::error::The audit agent finished without emitting a report or a noop. The prompt requires one of the two: create_issue with the findings, or noop when the codebase is clean. Nothing was filed and no reason was given, so this run is a failure rather than a clean audit. The next scheduled audit will try again. ${RUN_URL}"
|
|
156
|
+
exit 1
|
|
157
|
+
|
|
122
158
|
safe-outputs:
|
|
123
159
|
# A failed run is already a red run. An issue per failure buries the real backlog
|
|
124
160
|
# under noise nobody closes.
|
|
@@ -17,6 +17,13 @@ env:
|
|
|
17
17
|
STALLED_LABEL: stalled
|
|
18
18
|
PR_PENDING_LABEL: pr-pending
|
|
19
19
|
NO_PULL_REQUEST_COMMENT: "The implementation run finished without producing a pull request. Nothing was lost, but nothing landed either: the issue keeps `implement` and is flagged for a retry."
|
|
20
|
+
# Said when the agent DID write the code and the push failed. gh-aw pushes through the GraphQL
|
|
21
|
+
# signed-commits API, which rebases onto the current parent, so a `main` that moved under a long
|
|
22
|
+
# run conflicts; gh-aw keeps the work by filing the patch as an issue rather than dropping it,
|
|
23
|
+
# and comments the link on this issue itself. Telling someone "nothing landed" over the top of
|
|
24
|
+
# that sends them to reimplement work that already exists. One line: the compiler flattens a
|
|
25
|
+
# multi-line env value.
|
|
26
|
+
PUSH_CONFLICT_COMMENT: "The implementation produced a patch, but pushing it failed: it no longer applies to `main`, which moved while this ran. gh-aw filed the patch as a separate issue rather than losing it, and linked it in its own comment above. The work is there and needs rebasing onto current `main`, not writing again."
|
|
20
27
|
GIT_AUTHOR_NAME: "github-actions[bot]"
|
|
21
28
|
GIT_AUTHOR_EMAIL: "github-actions[bot]@users.noreply.github.com"
|
|
22
29
|
GIT_COMMITTER_NAME: "github-actions[bot]"
|
|
@@ -70,7 +77,37 @@ on:
|
|
|
70
77
|
required: false
|
|
71
78
|
type: string
|
|
72
79
|
default: '0'
|
|
80
|
+
# The gate job that the top-level `if:` reads. gh-aw folds that `if:` into the generated
|
|
81
|
+
# activation job but gives activation no dependency on the job, so the reference resolves
|
|
82
|
+
# to '' and the clause is false -- the agent would never run. The package's own validator
|
|
83
|
+
# catches it after compilation; this is the line it asks for, the same one the merge gate
|
|
84
|
+
# uses for protected_changes.
|
|
85
|
+
needs: [still_open]
|
|
73
86
|
jobs:
|
|
87
|
+
# A route dispatched while the issue was open must not execute after it has been closed. The
|
|
88
|
+
# classifier can only see `github.event.issue.state`, which is the state when the event fired
|
|
89
|
+
# and is absent on a workflow_dispatch, and this fleet queues for a runner for ten minutes and
|
|
90
|
+
# more. Numa #659 was closed one second after a comment dispatched refine; the run reached
|
|
91
|
+
# `reserve` thirteen minutes later and refined a closed issue to completion. Read now, once,
|
|
92
|
+
# and gate both the reservation and the agent on it.
|
|
93
|
+
still_open:
|
|
94
|
+
runs-on: agents-arc
|
|
95
|
+
permissions:
|
|
96
|
+
contents: read
|
|
97
|
+
issues: read
|
|
98
|
+
outputs:
|
|
99
|
+
open: ${{ steps.state.outputs.open }}
|
|
100
|
+
steps:
|
|
101
|
+
- name: Checkout workflow actions
|
|
102
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
103
|
+
with:
|
|
104
|
+
persist-credentials: false
|
|
105
|
+
- name: Read the issue state
|
|
106
|
+
id: state
|
|
107
|
+
uses: ./.github/actions/require-open-issue
|
|
108
|
+
with:
|
|
109
|
+
token: ${{ github.token }}
|
|
110
|
+
issue-number: ${{ inputs.issue-number }}
|
|
74
111
|
eligibility:
|
|
75
112
|
runs-on: agents-arc
|
|
76
113
|
permissions:
|
|
@@ -107,8 +144,8 @@ jobs:
|
|
|
107
144
|
echo "eligible=true" >> "$GITHUB_OUTPUT"
|
|
108
145
|
|
|
109
146
|
reserve:
|
|
110
|
-
needs: [eligibility]
|
|
111
|
-
if: needs.eligibility.outputs.eligible == 'true'
|
|
147
|
+
needs: [eligibility, still_open]
|
|
148
|
+
if: needs.eligibility.outputs.eligible == 'true' && needs.still_open.outputs.open == 'true'
|
|
112
149
|
runs-on: agents-arc
|
|
113
150
|
permissions:
|
|
114
151
|
contents: read
|
|
@@ -227,8 +264,43 @@ jobs:
|
|
|
227
264
|
# comment, and no bot-working — which also hid it from the hourly stale-reservation sweep.
|
|
228
265
|
# Comments do not re-trigger implement, so nothing on any path would ever look at it again.
|
|
229
266
|
# It was the only failure in the fleet that signalled nobody at all.
|
|
267
|
+
#
|
|
268
|
+
# There are two ways to reach "no pull request", and telling a person they are the same
|
|
269
|
+
# thing wastes their time. gh-aw pushes through the GraphQL signed-commits API, which
|
|
270
|
+
# rebases the commit range onto the current parent; when `main` has moved under a long run
|
|
271
|
+
# the rebase conflicts, and gh-aw keeps the work by filing the patch as an issue instead of
|
|
272
|
+
# dropping it, commenting the link on this issue itself. Saying "nothing landed" over the
|
|
273
|
+
# top of that is false: the patch exists and needs rebasing, not reimplementing. Seen on
|
|
274
|
+
# Numa #657, where the same change had landed on main by hand while the agent was writing
|
|
275
|
+
# it, and reproduced deliberately on dogfood #10 -> #11.
|
|
276
|
+
#
|
|
277
|
+
# The signal is the item counter, not `code_push_failure_count`. gh-aw treats the fallback
|
|
278
|
+
# as a *successful* outcome for the item -- the dogfood run logged `Status: success`,
|
|
279
|
+
# `Successful: 1` and a resolved `GH_AW_CODE_PUSH_FAILURE_COUNT: 0` while filing #11 -- so
|
|
280
|
+
# gating on that count posted the wrong message. `create_pull_request` is the only safe
|
|
281
|
+
# output this worker permits, so one succeeded item with no pull request number can only
|
|
282
|
+
# mean the push fell back to an issue. Nothing produced at all leaves the counter at 0.
|
|
283
|
+
- name: Flag a patch that could not be pushed
|
|
284
|
+
if: needs.safe_outputs.outputs.created_pr_number == '' && needs.safe_outputs.outputs.process_safe_outputs_items_succeeded != '0' && needs.safe_outputs.outputs.process_safe_outputs_items_succeeded != ''
|
|
285
|
+
uses: ./.github/actions/add-issue-labels
|
|
286
|
+
with:
|
|
287
|
+
token: ${{ steps.app-token.outputs.token }}
|
|
288
|
+
issue-number: ${{ inputs.issue-number }}
|
|
289
|
+
labels: |-
|
|
290
|
+
${{ env.REVIEW_LABEL }}
|
|
291
|
+
${{ env.STALLED_LABEL }}
|
|
292
|
+
- name: Say where the patch went
|
|
293
|
+
if: needs.safe_outputs.outputs.created_pr_number == '' && needs.safe_outputs.outputs.process_safe_outputs_items_succeeded != '0' && needs.safe_outputs.outputs.process_safe_outputs_items_succeeded != ''
|
|
294
|
+
uses: ./.github/actions/create-issue-comment
|
|
295
|
+
with:
|
|
296
|
+
token: ${{ steps.app-token.outputs.token }}
|
|
297
|
+
issue-number: ${{ inputs.issue-number }}
|
|
298
|
+
body: |
|
|
299
|
+
${{ env.IMPLEMENT_MARKER }}
|
|
300
|
+
${{ env.PUSH_CONFLICT_COMMENT }}
|
|
301
|
+
[View this workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
|
230
302
|
- name: Flag a run that produced no pull request
|
|
231
|
-
if: needs.safe_outputs.outputs.created_pr_number == ''
|
|
303
|
+
if: needs.safe_outputs.outputs.created_pr_number == '' && (needs.safe_outputs.outputs.process_safe_outputs_items_succeeded == '0' || needs.safe_outputs.outputs.process_safe_outputs_items_succeeded == '')
|
|
232
304
|
uses: ./.github/actions/add-issue-labels
|
|
233
305
|
with:
|
|
234
306
|
token: ${{ steps.app-token.outputs.token }}
|
|
@@ -237,7 +309,7 @@ jobs:
|
|
|
237
309
|
${{ env.REVIEW_LABEL }}
|
|
238
310
|
${{ env.STALLED_LABEL }}
|
|
239
311
|
- name: Say so on the issue
|
|
240
|
-
if: needs.safe_outputs.outputs.created_pr_number == ''
|
|
312
|
+
if: needs.safe_outputs.outputs.created_pr_number == '' && (needs.safe_outputs.outputs.process_safe_outputs_items_succeeded == '0' || needs.safe_outputs.outputs.process_safe_outputs_items_succeeded == '')
|
|
241
313
|
uses: ./.github/actions/create-issue-comment
|
|
242
314
|
with:
|
|
243
315
|
token: ${{ steps.app-token.outputs.token }}
|
|
@@ -436,7 +508,7 @@ jobs:
|
|
|
436
508
|
needs: [eligibility]
|
|
437
509
|
if: needs.eligibility.outputs.eligible == 'true'
|
|
438
510
|
|
|
439
|
-
if: inputs.issue-number != ''
|
|
511
|
+
if: inputs.issue-number != '' && needs.still_open.outputs.open == 'true'
|
|
440
512
|
|
|
441
513
|
runs-on: agents-arc
|
|
442
514
|
runs-on-slim: agents-arc
|