@plainconceptsplatform/workflows 0.4.33 → 0.4.34
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 +1 -1
- package/dist/action-validation.test.d.ts +1 -0
- package/dist/action-validation.test.js +84 -0
- package/dist/catalog-installation.js +27 -0
- package/dist/catalog-listing.test.js +1 -1
- package/dist/index.js +1 -1
- package/dist/index.test.js +6 -6
- package/dist/route-processing.test.js +12 -4
- package/dist/tui.test.js +8 -8
- package/dist/workflow-catalog.d.ts +1 -1
- package/dist/workflow-catalog.js +2 -0
- package/loops/actions/classify-route/action.yml +3 -0
- package/loops/actions/classify-route/classify-route.sh +38 -3
- package/loops/actions/load-issue-context/action.yml +2 -0
- package/loops/actions/validate-merge-gate-output/action.yml +40 -0
- package/loops/actions/validate-merge-gate-output/validate-merge-gate-output.sh +34 -0
- package/loops/actions/validate-review-output/action.yml +35 -0
- package/loops/actions/validate-review-output/validate-review-output.sh +30 -0
- package/loops/actions/validate-triage-output/action.yml +36 -0
- package/loops/actions/validate-triage-output/validate-triage-output.sh +36 -0
- package/loops/actions/verify-route-matrix/verify-route-matrix.sh +32 -2
- package/loops/workflows/agent-apply-review.md +89 -19
- package/loops/workflows/agent-audit.md +2 -2
- package/loops/workflows/agent-direct.md +14 -2
- package/loops/workflows/agent-implement.md +56 -16
- package/loops/workflows/agent-merge-gate.md +159 -60
- package/loops/workflows/agent-propose.md +1 -1
- package/loops/workflows/agent-refine.md +45 -6
- package/loops/workflows/agent-triage.md +439 -0
- package/loops/workflows/authorize-bot-work.yml +2 -1
- package/loops/workflows/work-router.yml +89 -8
- package/package.json +43 -42
|
@@ -68,6 +68,7 @@ jobs:
|
|
|
68
68
|
pr: ${{ steps.subject.outputs.pr }}
|
|
69
69
|
issue: ${{ steps.subject.outputs.issue }}
|
|
70
70
|
conclusion: ${{ steps.subject.outputs.conclusion }}
|
|
71
|
+
review_blocked: ${{ steps.review.outputs.review_blocked }}
|
|
71
72
|
steps:
|
|
72
73
|
- name: Checkout workflow actions
|
|
73
74
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
@@ -82,6 +83,16 @@ jobs:
|
|
|
82
83
|
ci-conclusion: ${{ inputs.ci-conclusion }}
|
|
83
84
|
linked-issue: ${{ inputs.linked-issue }}
|
|
84
85
|
require-label: ${{ env.IMPLEMENT_LABEL }}
|
|
86
|
+
- name: Block a pull request with requested changes
|
|
87
|
+
id: review
|
|
88
|
+
env:
|
|
89
|
+
GH_TOKEN: ${{ github.token }}
|
|
90
|
+
REPO: ${{ github.repository }}
|
|
91
|
+
PR: ${{ steps.subject.outputs.pr }}
|
|
92
|
+
run: |
|
|
93
|
+
set -euo pipefail
|
|
94
|
+
decision=$(gh pr view "$PR" --repo "$REPO" --json reviewDecision --jq '.reviewDecision')
|
|
95
|
+
echo "review_blocked=$([ "$decision" = 'CHANGES_REQUESTED' ] && echo true || echo false)" >> "$GITHUB_OUTPUT"
|
|
85
96
|
|
|
86
97
|
protected_changes:
|
|
87
98
|
needs: subject
|
|
@@ -102,7 +113,7 @@ jobs:
|
|
|
102
113
|
run: |
|
|
103
114
|
set -euo pipefail
|
|
104
115
|
files=$(gh api --paginate "repos/$REPO/pulls/$PR/files?per_page=100" --jq '.[].filename')
|
|
105
|
-
protected=$(printf '%s\n' "$files" | grep -E '^(\.|AGENTS\.md$|ARCHITECTURE\.md$|
|
|
116
|
+
protected=$(printf '%s\n' "$files" | grep -E '^(\.|AGENTS\.md$|ARCHITECTURE\.md$|opencode\.jsonc$|package\.json$|pnpm-lock\.yaml$|Directory\.Packages\.props$|global\.json$)' || true)
|
|
106
117
|
|
|
107
118
|
if [ -n "$protected" ]; then
|
|
108
119
|
echo "requires_review=true" >> "$GITHUB_OUTPUT"
|
|
@@ -118,35 +129,42 @@ jobs:
|
|
|
118
129
|
|
|
119
130
|
review_required:
|
|
120
131
|
needs: [subject, protected_changes]
|
|
121
|
-
|
|
132
|
+
# gh-aw makes the agent depend on custom jobs. Keep this job successful when
|
|
133
|
+
# there are no protected files instead of skipping it and blocking remediation.
|
|
134
|
+
if: always() && needs.subject.outputs.found == 'true'
|
|
122
135
|
runs-on: RunnerLandingZone
|
|
123
136
|
permissions:
|
|
124
137
|
contents: read
|
|
125
138
|
issues: write
|
|
126
139
|
steps:
|
|
127
140
|
- name: Checkout workflow actions
|
|
141
|
+
if: needs.protected_changes.outputs.requires_review == 'true'
|
|
128
142
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
129
143
|
with:
|
|
130
144
|
persist-credentials: false
|
|
131
145
|
- name: Create bot token
|
|
146
|
+
if: needs.protected_changes.outputs.requires_review == 'true'
|
|
132
147
|
id: app-token
|
|
133
148
|
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
|
134
149
|
with:
|
|
135
150
|
client-id: ${{ secrets.BOT_APP_ID }}
|
|
136
151
|
private-key: ${{ secrets.BOT_PRIVATE_KEY }}
|
|
137
152
|
- name: Release the issue
|
|
153
|
+
if: needs.protected_changes.outputs.requires_review == 'true'
|
|
138
154
|
uses: ./.github/actions/remove-issue-labels
|
|
139
155
|
with:
|
|
140
156
|
token: ${{ steps.app-token.outputs.token }}
|
|
141
157
|
issue-number: ${{ needs.subject.outputs.issue }}
|
|
142
158
|
labels: ${{ env.WORKING_LABEL }}
|
|
143
159
|
- name: Flag human review
|
|
160
|
+
if: needs.protected_changes.outputs.requires_review == 'true'
|
|
144
161
|
uses: ./.github/actions/add-issue-labels
|
|
145
162
|
with:
|
|
146
163
|
token: ${{ steps.app-token.outputs.token }}
|
|
147
164
|
issue-number: ${{ needs.subject.outputs.issue }}
|
|
148
165
|
labels: ${{ env.REVIEW_LABEL }}
|
|
149
166
|
- name: Explain the merge hold
|
|
167
|
+
if: needs.protected_changes.outputs.requires_review == 'true'
|
|
150
168
|
uses: ./.github/actions/create-issue-comment
|
|
151
169
|
with:
|
|
152
170
|
token: ${{ steps.app-token.outputs.token }}
|
|
@@ -167,6 +185,8 @@ jobs:
|
|
|
167
185
|
contents: read
|
|
168
186
|
issues: write
|
|
169
187
|
pull-requests: read
|
|
188
|
+
outputs:
|
|
189
|
+
has_conflicts: ${{ steps.conflicts.outputs.has_conflicts || 'false' }}
|
|
170
190
|
steps:
|
|
171
191
|
- name: Checkout workflow actions
|
|
172
192
|
if: needs.subject.outputs.conclusion == 'failure'
|
|
@@ -205,11 +225,41 @@ jobs:
|
|
|
205
225
|
${{ env.GATE_MARKER }}
|
|
206
226
|
Problems found in PR #${{ needs.subject.outputs.pr }}. ${{ steps.conflicts.outputs.has_conflicts == 'true' && 'Merge conflicts detected.' || 'CI failed.' }}
|
|
207
227
|
Bot is working on fixing it.
|
|
228
|
+
validate_output:
|
|
229
|
+
needs: [activation, agent, safe_outputs]
|
|
230
|
+
if: >
|
|
231
|
+
always() &&
|
|
232
|
+
needs.agent.result == 'success' &&
|
|
233
|
+
needs.safe_outputs.result == 'success'
|
|
234
|
+
runs-on: RunnerLandingZone
|
|
235
|
+
permissions:
|
|
236
|
+
contents: read
|
|
237
|
+
outputs:
|
|
238
|
+
valid: ${{ steps.validate.outputs.valid }}
|
|
239
|
+
outcome: ${{ steps.validate.outputs.outcome }}
|
|
240
|
+
steps:
|
|
241
|
+
- name: Checkout workflow actions
|
|
242
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
243
|
+
with:
|
|
244
|
+
persist-credentials: false
|
|
245
|
+
- name: Download agent output
|
|
246
|
+
id: output
|
|
247
|
+
uses: ./.github/actions/download-agent-output
|
|
248
|
+
with:
|
|
249
|
+
artifact-name: ${{ needs.activation.outputs.artifact_prefix }}agent
|
|
250
|
+
- name: Validate merge-gate outcome
|
|
251
|
+
id: validate
|
|
252
|
+
uses: ./.github/actions/validate-merge-gate-output
|
|
253
|
+
with:
|
|
254
|
+
output-file: ${{ steps.output.outputs.output-file }}
|
|
255
|
+
issue-number: ${{ needs.subject.outputs.issue }}
|
|
256
|
+
ci-conclusion: ${{ needs.subject.outputs.conclusion }}
|
|
208
257
|
conclude:
|
|
209
|
-
needs: [activation, subject, protected_changes, agent, safe_outputs]
|
|
258
|
+
needs: [activation, subject, protected_changes, agent, safe_outputs, validate_output]
|
|
210
259
|
if: >
|
|
211
260
|
needs.agent.result == 'success' &&
|
|
212
|
-
|
|
261
|
+
needs.safe_outputs.result == 'success' &&
|
|
262
|
+
needs.validate_output.outputs.valid == 'true' &&
|
|
213
263
|
needs.protected_changes.outputs.requires_review != 'true'
|
|
214
264
|
runs-on: RunnerLandingZone
|
|
215
265
|
permissions:
|
|
@@ -240,16 +290,57 @@ jobs:
|
|
|
240
290
|
with:
|
|
241
291
|
artifact-name: ${{ needs.activation.outputs.artifact_prefix }}agent
|
|
242
292
|
token: ${{ steps.app-token.outputs.token }}
|
|
243
|
-
merge-pull-request: 'true'
|
|
244
293
|
push-to-branch: 'true'
|
|
245
|
-
|
|
294
|
+
apply-labels: 'false'
|
|
295
|
+
- name: Merge approved pull request
|
|
296
|
+
if: needs.validate_output.outputs.outcome == 'merge'
|
|
297
|
+
env:
|
|
298
|
+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
299
|
+
REPO: ${{ github.repository }}
|
|
300
|
+
PR: ${{ needs.subject.outputs.pr }}
|
|
301
|
+
run: |
|
|
302
|
+
set -euo pipefail
|
|
303
|
+
head_sha=$(gh pr view "$PR" --repo "$REPO" --json headRefOid --jq '.headRefOid')
|
|
304
|
+
gh pr merge "$PR" --repo "$REPO" --squash --match-head-commit "$head_sha"
|
|
305
|
+
- name: Release remediated issue
|
|
306
|
+
if: needs.validate_output.outputs.outcome == 'remediated'
|
|
307
|
+
uses: ./.github/actions/remove-issue-labels
|
|
308
|
+
with:
|
|
309
|
+
token: ${{ steps.app-token.outputs.token }}
|
|
310
|
+
issue-number: ${{ needs.subject.outputs.issue }}
|
|
311
|
+
labels: ${{ env.WORKING_LABEL }}
|
|
312
|
+
- name: Flag review outcome
|
|
313
|
+
if: needs.validate_output.outputs.outcome == 'review'
|
|
314
|
+
uses: ./.github/actions/add-issue-labels
|
|
315
|
+
with:
|
|
316
|
+
token: ${{ steps.app-token.outputs.token }}
|
|
317
|
+
issue-number: ${{ needs.subject.outputs.issue }}
|
|
318
|
+
labels: ${{ env.REVIEW_LABEL }}
|
|
319
|
+
- name: Release review outcome
|
|
320
|
+
if: needs.validate_output.outputs.outcome == 'review'
|
|
321
|
+
uses: ./.github/actions/remove-issue-labels
|
|
322
|
+
with:
|
|
323
|
+
token: ${{ steps.app-token.outputs.token }}
|
|
324
|
+
issue-number: ${{ needs.subject.outputs.issue }}
|
|
325
|
+
labels: ${{ env.WORKING_LABEL }}
|
|
326
|
+
- name: Clear merged issue labels
|
|
327
|
+
if: needs.validate_output.outputs.outcome == 'merge'
|
|
328
|
+
uses: ./.github/actions/remove-issue-labels
|
|
329
|
+
with:
|
|
330
|
+
token: ${{ steps.app-token.outputs.token }}
|
|
331
|
+
issue-number: ${{ needs.subject.outputs.issue }}
|
|
332
|
+
labels: ${{ env.IMPLEMENT_LABEL }},${{ env.WORKING_LABEL }},${{ env.REVIEW_LABEL }}
|
|
246
333
|
incomplete:
|
|
247
|
-
needs: [subject, protected_changes, agent, safe_outputs]
|
|
334
|
+
needs: [subject, protected_changes, agent, safe_outputs, validate_output]
|
|
248
335
|
if: >
|
|
249
336
|
always() &&
|
|
250
337
|
needs.subject.outputs.found == 'true' &&
|
|
251
338
|
needs.protected_changes.outputs.requires_review != 'true' &&
|
|
252
|
-
|
|
339
|
+
(
|
|
340
|
+
needs.agent.result != 'success' ||
|
|
341
|
+
needs.safe_outputs.result != 'success' ||
|
|
342
|
+
needs.validate_output.outputs.valid != 'true'
|
|
343
|
+
)
|
|
253
344
|
runs-on: RunnerLandingZone
|
|
254
345
|
permissions:
|
|
255
346
|
contents: read
|
|
@@ -289,10 +380,12 @@ jobs:
|
|
|
289
380
|
[View this workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
|
290
381
|
|
|
291
382
|
agent:
|
|
292
|
-
|
|
293
|
-
|
|
383
|
+
# The top-level guard reads both outputs. GitHub Actions does not make a
|
|
384
|
+
# dependency's dependencies available through `needs` transitively.
|
|
385
|
+
needs: [subject, protected_changes]
|
|
386
|
+
if: always() && needs.protected_changes.outputs.requires_review != 'true' && needs.subject.outputs.review_blocked != 'true'
|
|
294
387
|
|
|
295
|
-
if: needs.subject.outputs.found == 'true' && needs.protected_changes.outputs.requires_review != 'true'
|
|
388
|
+
if: always() && needs.subject.outputs.found == 'true' && needs.protected_changes.outputs.requires_review != 'true' && needs.subject.outputs.review_blocked != 'true'
|
|
296
389
|
|
|
297
390
|
runs-on: RunnerLandingZone
|
|
298
391
|
runs-on-slim: RunnerLandingZone
|
|
@@ -354,12 +447,9 @@ steps:
|
|
|
354
447
|
safe-outputs:
|
|
355
448
|
staged: true
|
|
356
449
|
threat-detection: false
|
|
357
|
-
merge-pull-request:
|
|
358
450
|
push-to-pull-request-branch:
|
|
359
|
-
close-issue:
|
|
360
451
|
add-comment:
|
|
361
|
-
|
|
362
|
-
remove-labels:
|
|
452
|
+
target: "*"
|
|
363
453
|
|
|
364
454
|
timeout-minutes: 60
|
|
365
455
|
---
|
|
@@ -378,19 +468,23 @@ timeout-minutes: 60
|
|
|
378
468
|
|
|
379
469
|
3. Branch on the conclusion.
|
|
380
470
|
|
|
471
|
+
First check the issue context for `<!-- complexity: trivial -->`.
|
|
472
|
+
|
|
473
|
+
**If the trivial marker is present AND CI conclusion is success:**
|
|
474
|
+
Skip the risk assessment (step 4). Proceed directly to step 5 (merge).
|
|
475
|
+
The change is presentation-only and CI is green — no need for deep risk review.
|
|
476
|
+
Trivial changes do not touch business logic, data models, auth, or infrastructure by definition.
|
|
477
|
+
|
|
478
|
+
**If the trivial marker is absent OR CI is not success:**
|
|
479
|
+
Follow the normal branching below.
|
|
480
|
+
|
|
381
481
|
- **success** → step 4.
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
(item_number: ${{ needs.subject.outputs.issue }}), and `add_comment`
|
|
386
|
-
(item_number: ${{ needs.subject.outputs.issue }}) saying CI requires
|
|
387
|
-
workflow approval before it can run, and a maintainer must approve the
|
|
388
|
-
pending run. Then stop , do not attempt to merge or fix.
|
|
482
|
+
- **action_required** → CI did not run because the workflow needs approval.
|
|
483
|
+
Proceed to review: explain that a maintainer must approve the pending run.
|
|
484
|
+
Do not attempt to merge or fix.
|
|
389
485
|
- **failure** → step 7.
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
then `add_labels` to add `review` (item_number: the issue), and stop.
|
|
393
|
-
A cancelled or unknown run is not evidence of anything.
|
|
486
|
+
- **cancelled, timed_out, or anything else** → proceed to review. A cancelled or unknown
|
|
487
|
+
run is not evidence of anything.
|
|
394
488
|
|
|
395
489
|
Follow repository documentation and established conventions when assessing or remediating
|
|
396
490
|
the pull request. Protect secrets, do not bypass checks, and keep remediation focused.
|
|
@@ -410,45 +504,47 @@ timeout-minutes: 60
|
|
|
410
504
|
- The diff is materially larger than the issue implied.
|
|
411
505
|
- You are simply not confident. Low confidence is itself a flag.
|
|
412
506
|
|
|
413
|
-
5. **Clean assessment** →
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
fix the actual cause. Run these verification commands before a push. Do not weaken a test,
|
|
431
|
-
disable a check, or push an unverified guess.
|
|
507
|
+
5. **Clean assessment** → select the `merge` verdict.
|
|
508
|
+
|
|
509
|
+
6. **Flagged** → select the `review` verdict. Do not merge. Explain exactly which criterion
|
|
510
|
+
tripped and what a reviewer should look at. Leave `implement` in place: the work is not
|
|
511
|
+
finished until a human merges it.
|
|
512
|
+
|
|
513
|
+
7. **CI failed** → read `/tmp/gh-aw/agent/failed-jobs.json` and
|
|
514
|
+
`/tmp/gh-aw/agent/failed-logs.txt`, which are already on disk. Load only skills required to
|
|
515
|
+
fix the actual cause. Run these verification commands before a push. Do not weaken a test,
|
|
516
|
+
disable a check, or push an unverified guess.
|
|
517
|
+
|
|
518
|
+
**If `has_conflicts` is `true` (current value: `${{ needs.reserve.outputs.has_conflicts }}`):** You are already on the PR branch. Resolve the conflict;
|
|
519
|
+
it is not a reason to hand the PR to a human. Merge `origin/${{ github.event.repository.default_branch }}`
|
|
520
|
+
into the current branch, resolve every conflict deliberately, stage the resolutions, and
|
|
521
|
+
commit the merge. Then run verification and push the resulting branch update. Do not use
|
|
522
|
+
`--ours`, `--theirs`, or a blanket conflict-marker deletion without reviewing the intended
|
|
523
|
+
behavior from both sides.
|
|
432
524
|
|
|
433
525
|
```
|
|
434
526
|
${{ env.VERIFY_COMMANDS }}
|
|
435
527
|
```
|
|
436
528
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
529
|
+
Propose `push_to_pull_request_branch` (pr_number: ${{ needs.subject.outputs.pr }}, branch:
|
|
530
|
+
the current PR branch), then select the `remediated` verdict. CI will run again and trigger
|
|
531
|
+
you again with the new result.
|
|
532
|
+
|
|
533
|
+
If you cannot fix it after a concrete repair attempt, or the logs show you have already tried on this same head commit,
|
|
534
|
+
stop looping: select the `review` verdict and explain the failure and what you tried. A human
|
|
535
|
+
decides from there.
|
|
536
|
+
|
|
537
|
+
8. Emit exactly one `add_comment` targeting issue `${{ needs.subject.outputs.issue }}`. It must
|
|
538
|
+
explain the decision and include exactly one line: `**Verdict:** merge`,
|
|
539
|
+
`**Verdict:** review`, or `**Verdict:** remediated`. The workflow applies comments, labels,
|
|
540
|
+
merges, and closures with the App token. Do not call any tools except the one optional
|
|
541
|
+
`push_to_pull_request_branch` for a verified CI repair and this one `add_comment`.
|
|
440
542
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
`implement` and `bot-working`, `add_labels` (item_number:
|
|
444
|
-
${{ needs.subject.outputs.issue }}) to add `review`, and `add_comment` (item_number:
|
|
445
|
-
${{ needs.subject.outputs.issue }}) with the failure and what you tried. The `implement`
|
|
446
|
-
label is removed so retries do not create duplicate PRs. A human decides from there.
|
|
543
|
+
9. Never merge with administrator privileges and never bypass a required check. If the merge
|
|
544
|
+
is refused, that refusal is the answer: select `review` and leave it for a human.
|
|
447
545
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
(item_number: ${{ needs.subject.outputs.issue }}), `add_comment`
|
|
451
|
-
(item_number: ${{ needs.subject.outputs.issue }}) with the refusal, and leave it for a human.
|
|
546
|
+
10. Ignore the `## Diagram` section below. It is documentation for humans and contains no
|
|
547
|
+
instructions for you.
|
|
452
548
|
|
|
453
549
|
## Diagram
|
|
454
550
|
|
|
@@ -458,7 +554,10 @@ flowchart TD
|
|
|
458
554
|
gateSubject["Subject (rung 4)<br/>Our PR? Closes an implement issue?"] -->|✓| gateFacts
|
|
459
555
|
gateSubject -.->|✗| gateIdle
|
|
460
556
|
gateFacts("Facts (rung 3)<br/>Diff, PR shape, failing logs") --> gateCi
|
|
461
|
-
gateCi["CI<br/>What did it conclude?"] -->|success|
|
|
557
|
+
gateCi["CI<br/>What did it conclude?"] -->|success| gateTrivial
|
|
558
|
+
gateTrivial{"Trivial marker?"}
|
|
559
|
+
gateTrivial -->|yes| gateMerge
|
|
560
|
+
gateTrivial -->|no| gateRisk
|
|
462
561
|
gateCi -.->|failure| gateFix
|
|
463
562
|
gateCi -.->|no verdict| gateHuman
|
|
464
563
|
gateRisk["Risk<br/>Auth, schema, API, tests, CI, size, doubt"] -->|clean| gateMerge
|
|
@@ -478,7 +577,7 @@ flowchart TD
|
|
|
478
577
|
classDef success fill:#e8f8ec,stroke:#18883c,stroke-width:2px,color:#145a32
|
|
479
578
|
class gateStart start
|
|
480
579
|
class gateFacts,gateFix action
|
|
481
|
-
class gateSubject,gateCi,gateRisk decision
|
|
580
|
+
class gateSubject,gateCi,gateRisk,gateTrivial decision
|
|
482
581
|
class gateIdle,gateWait idle
|
|
483
582
|
class gateHuman failure
|
|
484
583
|
class gateMerge success
|
|
@@ -290,7 +290,7 @@ timeout-minutes: 45
|
|
|
290
290
|
Write all four, not just the winner. Next run reads this to avoid re-deriving the three that
|
|
291
291
|
lost. A body containing only the winner makes this workflow amnesiac.
|
|
292
292
|
|
|
293
|
-
**Section 2, The proposal:** Call skill("
|
|
293
|
+
**Section 2, The proposal:** Call skill("pc-plan-story") and refine the highest scorer into a
|
|
294
294
|
user story in Mike Cohn's As a / I want to / so that form, with Given/When/Then acceptance
|
|
295
295
|
criteria, edge cases, and the likely files to change.
|
|
296
296
|
|
|
@@ -11,6 +11,7 @@ env:
|
|
|
11
11
|
INITIAL_MODE: first
|
|
12
12
|
RESPONSE_MODE: rerefine
|
|
13
13
|
MAX_SELF_QUESTIONS: "5"
|
|
14
|
+
TRIVIAL_MARKER: "<!-- complexity: trivial -->"
|
|
14
15
|
INCOMPLETE_COMMENT: "Automated refinement ended without an outcome. The refine label remains for a retry."
|
|
15
16
|
SAFE_OUTPUT_COMMENT_PREFIX: "Refinement update"
|
|
16
17
|
ISSUE_CONTEXT_PATH: /tmp/gh-aw/agent/issue-context.json
|
|
@@ -275,7 +276,7 @@ timeout-minutes: 40
|
|
|
275
276
|
- On a `${{ env.RESPONSE_MODE }}` pass, incorporate only the supplied answers from the issue author or an
|
|
276
277
|
assignee. Do not use answers from other commenters.
|
|
277
278
|
|
|
278
|
-
3. Explore before you write. Call skill("
|
|
279
|
+
3. Explore before you write. Call skill("pc-plan-explore") and hold its stance for this step:
|
|
279
280
|
read-only, no plans, no files, no branches. You are only building understanding here, never
|
|
280
281
|
producing artifacts.
|
|
281
282
|
|
|
@@ -304,9 +305,38 @@ timeout-minutes: 40
|
|
|
304
305
|
longer changes your understanding. This exploration is internal working: never write your
|
|
305
306
|
self-asked questions or their answers to the issue.
|
|
306
307
|
|
|
307
|
-
4.
|
|
308
|
+
4. **Classify the change complexity.** Based on your exploration, determine whether this is a
|
|
309
|
+
trivial change. A change is **trivial** if ALL of these are true:
|
|
310
|
+
|
|
311
|
+
- It touches 1-3 files: CSS, Tailwind classes, text labels, markup, or styling only
|
|
312
|
+
- No business logic: no services, controllers, domain models, calculations, validations
|
|
313
|
+
- No data model: no entities, migrations, DTOs, API contracts
|
|
314
|
+
- No security surface: no auth, authorization, secrets, tokens, permissions
|
|
315
|
+
- No infrastructure: no Bicep, Docker, CI, deploy configuration
|
|
316
|
+
- No cross-cutting: doesn't touch shared libraries or multi-team contracts
|
|
317
|
+
|
|
318
|
+
If ALL pass → **trivial path** (step 4a). If ANY fail → **standard path** (step 5).
|
|
319
|
+
|
|
320
|
+
**4a. Trivial path.** Skip `/plan-story`. Do not write Gherkin acceptance criteria or
|
|
321
|
+
Mermaid diagrams. Instead, prepare the replacement issue body as valid Markdown:
|
|
322
|
+
|
|
323
|
+
1. `${{ env.TRIVIAL_MARKER }}`
|
|
324
|
+
2. A short plain-English summary of what needs to change and why (2-3 sentences max)
|
|
325
|
+
3. A simple checklist of concrete steps:
|
|
326
|
+
```
|
|
327
|
+
## Tasks
|
|
328
|
+
- [ ] Change X in file Y
|
|
329
|
+
- [ ] Verify Z
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
No "As a / I want / so that" form. No Given/When/Then. No Mermaid. Just the marker,
|
|
333
|
+
the summary, and the checklist.
|
|
334
|
+
|
|
335
|
+
Load `@humanizer` and prepare the replacement issue body, then go directly to step 6.
|
|
336
|
+
|
|
337
|
+
5. Before writing the story, verify coverage: list every work unit and confirm each one has
|
|
308
338
|
exploration findings concrete enough for acceptance criteria. If any unit is missing, go back
|
|
309
|
-
and explore it now. Then call skill("
|
|
339
|
+
and explore it now. Then call skill("pc-plan-story") and run `/plan-story` for the issue,
|
|
310
340
|
passing everything you learned while exploring as the exploration findings. Ground the story
|
|
311
341
|
in the actual codebase by reading the relevant files. Never read outside this repository root.
|
|
312
342
|
When the issue held several work units, combine them into a single user story that covers all
|
|
@@ -323,6 +353,11 @@ timeout-minutes: 40
|
|
|
323
353
|
|
|
324
354
|
Labels are workflow-owned state. Do not call `add_labels` or `remove_labels`.
|
|
325
355
|
|
|
356
|
+
**Do not probe safe-output tools.** Never call `update_issue` or `add_comment` with
|
|
357
|
+
empty or test arguments — each safe-output type has a per-run limit of 1 call, and a
|
|
358
|
+
probe call consumes that quota. Call a safe-output tool exactly once, with the full
|
|
359
|
+
final payload, when you are ready to commit to the outcome.
|
|
360
|
+
|
|
326
361
|
**Questions remain.** You set aside one or more questions for the author that the codebase
|
|
327
362
|
could not answer. Leave the body unchanged. Call `add_comment` once with:
|
|
328
363
|
1. `${{ env.REFINE_MARKER }}`
|
|
@@ -351,7 +386,11 @@ flowchart TD
|
|
|
351
386
|
refPick -.->|no| refIdle
|
|
352
387
|
refReserve("Reserve<br/>bot-working") --> refFacts
|
|
353
388
|
refFacts("Facts<br/>Issue and comments to disk") --> refExplore
|
|
354
|
-
refExplore("Explore<br/>
|
|
389
|
+
refExplore("Explore<br/>pc-plan-explore per work unit,<br/>self-answer, bounded") --> refClassify
|
|
390
|
+
refClassify{"Trivial change?"}
|
|
391
|
+
refClassify -->|yes: trivial path| refTrivial
|
|
392
|
+
refClassify -->|no: standard path| refStory
|
|
393
|
+
refTrivial("Trivial plan<br/>marker + summary + checklist") -->|✓| refProse
|
|
355
394
|
refStory("Story<br/>/plan-story, grounded in the code") -->|✓| refProse
|
|
356
395
|
refStory -.->|✗| refFail
|
|
357
396
|
refProse("Prose<br/>@humanizer over the final text") -->|✓| refOutcome
|
|
@@ -371,8 +410,8 @@ flowchart TD
|
|
|
371
410
|
classDef success fill:#e8f8ec,stroke:#18883c,stroke-width:2px,color:#145a32
|
|
372
411
|
|
|
373
412
|
class refStart start
|
|
374
|
-
class refReserve,refFacts,refExplore,refStory,refProse action
|
|
375
|
-
class refPick,refOutcome decision
|
|
413
|
+
class refReserve,refFacts,refExplore,refStory,refTrivial,refProse action
|
|
414
|
+
class refPick,refOutcome,refClassify decision
|
|
376
415
|
class refIdle idle
|
|
377
416
|
class refFail failure
|
|
378
417
|
class refDone,refAsk success
|