@plainconceptsplatform/workflows 1.2.3 → 1.3.1

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.
Files changed (45) hide show
  1. package/dist/route-processing.js +1 -0
  2. package/loops/actions/add-issue-labels/action.yml +50 -50
  3. package/loops/actions/agent-output.cjs +17 -17
  4. package/loops/actions/apply-agent-bundle/action.yml +24 -24
  5. package/loops/actions/apply-agent-comments/action.yml +42 -42
  6. package/loops/actions/apply-agent-labels/action.yml +55 -55
  7. package/loops/actions/apply-agent-output/action.yml +108 -108
  8. package/loops/actions/assess-blast-radius/action.yml +47 -8
  9. package/loops/actions/assess-blast-radius/assess-blast-radius.sh +27 -5
  10. package/loops/actions/assess-blast-radius/migration-is-additive.sh +38 -0
  11. package/loops/actions/classify-route/action.yml +2 -1
  12. package/loops/actions/classify-route/classify-route.sh +7 -1
  13. package/loops/actions/cleanup-artifacts/action.yml +91 -91
  14. package/loops/actions/close-agent-issues/action.yml +43 -43
  15. package/loops/actions/create-agent-issues/action.yml +52 -52
  16. package/loops/actions/create-issue-comment/action.yml +29 -29
  17. package/loops/actions/download-agent-output/action.yml +53 -53
  18. package/loops/actions/link-pr-to-issue/action.yml +40 -40
  19. package/loops/actions/list-open-issues/action.yml +33 -33
  20. package/loops/actions/load-issue-context/action.yml +45 -45
  21. package/loops/actions/merge-agent-pr/action.yml +49 -49
  22. package/loops/actions/push-agent-branch/action.yml +45 -45
  23. package/loops/actions/remove-issue-labels/action.yml +37 -37
  24. package/loops/actions/update-agent-issues/action.yml +58 -58
  25. package/loops/actions/validate-merge-gate-output/action.yml +6 -1
  26. package/loops/actions/validate-merge-gate-output/validate-merge-gate-output.sh +9 -2
  27. package/loops/actions/validate-review-output/action.yml +35 -35
  28. package/loops/actions/validate-triage-output/action.yml +36 -36
  29. package/loops/actions/verify-composite-actions/action.yml +9 -9
  30. package/loops/actions/verify-refine-output/action.yml +9 -9
  31. package/loops/actions/verify-route-matrix/action.yml +9 -9
  32. package/loops/actions/verify-route-matrix/verify-route-matrix.sh +149 -29
  33. package/loops/docs/diagrams.md +26 -11
  34. package/loops/templates/agentics/agentics-maintenance.yml +121 -121
  35. package/loops/templates/issues/bug_report.yml +109 -109
  36. package/loops/templates/issues/feature_request.yml +75 -75
  37. package/loops/templates/release/github-release.yml +30 -30
  38. package/loops/workflows/agent-apply-review.md +5 -0
  39. package/loops/workflows/agent-implement.md +6 -0
  40. package/loops/workflows/agent-merge-gate.md +100 -3
  41. package/loops/workflows/authorize-bot-work.yml +105 -105
  42. package/loops/workflows/evidence.yml +79 -4
  43. package/loops/workflows/shared/platform-defaults.md +23 -23
  44. package/loops/workflows/work-router.yml +97 -21
  45. package/package.json +1 -1
@@ -1,109 +1,109 @@
1
- name: Bug report
2
- description: Report a defect
3
- labels: ["bug"]
4
- body:
5
- - type: markdown
6
- attributes:
7
- value: |
8
- Thanks for reporting. Do **not** include real secrets or production data use placeholders.
9
-
10
- For security vulnerabilities, contact the team directly instead of filing a public issue.
11
- - type: dropdown
12
- id: severity
13
- attributes:
14
- label: Severity
15
- options:
16
- - Production-down / data loss
17
- - Major broken core flow
18
- - Minor broken edge case
19
- - Cosmetic / polish
20
- validations:
21
- required: true
22
- - type: dropdown
23
- id: frequency
24
- attributes:
25
- label: Frequency
26
- description: How often does this happen?
27
- options:
28
- - Always
29
- - Intermittent
30
- - Only once
31
- validations:
32
- required: true
33
- - type: textarea
34
- id: what-happened
35
- attributes:
36
- label: What happened?
37
- description: A clear description of the bug and its impact.
38
- validations:
39
- required: true
40
- - type: textarea
41
- id: repro
42
- attributes:
43
- label: Steps to reproduce
44
- description: How can a maintainer reproduce it?
45
- placeholder: |
46
- 1. Go to ...
47
- 2. Do ...
48
- 3. See error
49
- validations:
50
- required: true
51
- - type: textarea
52
- id: expected
53
- attributes:
54
- label: Expected behavior
55
- validations:
56
- required: true
57
- - type: dropdown
58
- id: area
59
- attributes:
60
- label: Where does it occur?
61
- options:
62
- - Backend
63
- - Frontend
64
- - Both
65
- - CLI / tooling
66
- - Configuration / deployment
67
- - Documentation
68
- - Other
69
- validations:
70
- required: true
71
- - type: textarea
72
- id: acceptance
73
- attributes:
74
- label: Acceptance criteria
75
- description: How will we know it's fixed? A checklist a reviewer can verify (include the test that should turn green).
76
- placeholder: |
77
- - [ ] ...
78
- - [ ] A test that fails before the fix and passes after
79
- validations:
80
- required: false
81
- - type: textarea
82
- id: open-questions
83
- attributes:
84
- label: Open questions
85
- description: Decisions a maintainer must make before this can be planned. Leave blank if none.
86
- validations:
87
- required: false
88
- - type: textarea
89
- id: environment
90
- attributes:
91
- label: Environment
92
- description: Local vs deployed, branch/commit, OS, runtime versions if relevant.
93
- validations:
94
- required: false
95
- - type: textarea
96
- id: logs
97
- attributes:
98
- label: Logs / screenshots
99
- description: Paste relevant logs or screenshots. Redact secrets and PII.
100
- render: shell
101
- validations:
102
- required: false
103
- - type: textarea
104
- id: related
105
- attributes:
106
- label: Related links
107
- description: Links to related issues, PRs, discussions, or docs. Leave blank if none.
108
- validations:
109
- required: false
1
+ name: Bug report
2
+ description: Report a defect
3
+ labels: ["bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for reporting. Do **not** include real secrets or production data use placeholders.
9
+
10
+ For security vulnerabilities, contact the team directly instead of filing a public issue.
11
+ - type: dropdown
12
+ id: severity
13
+ attributes:
14
+ label: Severity
15
+ options:
16
+ - Production-down / data loss
17
+ - Major broken core flow
18
+ - Minor broken edge case
19
+ - Cosmetic / polish
20
+ validations:
21
+ required: true
22
+ - type: dropdown
23
+ id: frequency
24
+ attributes:
25
+ label: Frequency
26
+ description: How often does this happen?
27
+ options:
28
+ - Always
29
+ - Intermittent
30
+ - Only once
31
+ validations:
32
+ required: true
33
+ - type: textarea
34
+ id: what-happened
35
+ attributes:
36
+ label: What happened?
37
+ description: A clear description of the bug and its impact.
38
+ validations:
39
+ required: true
40
+ - type: textarea
41
+ id: repro
42
+ attributes:
43
+ label: Steps to reproduce
44
+ description: How can a maintainer reproduce it?
45
+ placeholder: |
46
+ 1. Go to ...
47
+ 2. Do ...
48
+ 3. See error
49
+ validations:
50
+ required: true
51
+ - type: textarea
52
+ id: expected
53
+ attributes:
54
+ label: Expected behavior
55
+ validations:
56
+ required: true
57
+ - type: dropdown
58
+ id: area
59
+ attributes:
60
+ label: Where does it occur?
61
+ options:
62
+ - Backend
63
+ - Frontend
64
+ - Both
65
+ - CLI / tooling
66
+ - Configuration / deployment
67
+ - Documentation
68
+ - Other
69
+ validations:
70
+ required: true
71
+ - type: textarea
72
+ id: acceptance
73
+ attributes:
74
+ label: Acceptance criteria
75
+ description: How will we know it's fixed? A checklist a reviewer can verify (include the test that should turn green).
76
+ placeholder: |
77
+ - [ ] ...
78
+ - [ ] A test that fails before the fix and passes after
79
+ validations:
80
+ required: false
81
+ - type: textarea
82
+ id: open-questions
83
+ attributes:
84
+ label: Open questions
85
+ description: Decisions a maintainer must make before this can be planned. Leave blank if none.
86
+ validations:
87
+ required: false
88
+ - type: textarea
89
+ id: environment
90
+ attributes:
91
+ label: Environment
92
+ description: Local vs deployed, branch/commit, OS, runtime versions if relevant.
93
+ validations:
94
+ required: false
95
+ - type: textarea
96
+ id: logs
97
+ attributes:
98
+ label: Logs / screenshots
99
+ description: Paste relevant logs or screenshots. Redact secrets and PII.
100
+ render: shell
101
+ validations:
102
+ required: false
103
+ - type: textarea
104
+ id: related
105
+ attributes:
106
+ label: Related links
107
+ description: Links to related issues, PRs, discussions, or docs. Leave blank if none.
108
+ validations:
109
+ required: false
@@ -1,75 +1,75 @@
1
- name: Feature request
2
- description: Propose a small improvement or new capability
3
- labels: ["enhancement"]
4
- body:
5
- - type: markdown
6
- attributes:
7
- value: |
8
- This template is for small, well-scoped improvements a focused
9
- enhancement, a missing convenience, a quality-of-life fix.
10
-
11
- For large features, architecture changes, or cross-cutting work,
12
- open a planning issue or an ADR instead.
13
-
14
- Do **not** include real secrets or production data use placeholders.
15
- - type: dropdown
16
- id: scope
17
- attributes:
18
- label: Scope
19
- description: How big is this change? If it doesn't fit Small or Medium, use a planning issue instead.
20
- options:
21
- - Small a single file or component, no refactoring
22
- - Medium touches a few files or a feature area, may need minor refactoring
23
- validations:
24
- required: true
25
- - type: textarea
26
- id: current-behavior
27
- attributes:
28
- label: Current behavior
29
- description: How does it work today? Describe the existing behavior or limitation.
30
- validations:
31
- required: true
32
- - type: textarea
33
- id: problem
34
- attributes:
35
- label: Problem / motivation
36
- description: What user or business need does this address? Why is the current behavior a problem?
37
- validations:
38
- required: true
39
- - type: textarea
40
- id: proposal
41
- attributes:
42
- label: Proposed solution
43
- description: What would you like to happen?
44
- validations:
45
- required: true
46
- - type: textarea
47
- id: alternatives
48
- attributes:
49
- label: Alternatives considered
50
- validations:
51
- required: false
52
- - type: textarea
53
- id: acceptance
54
- attributes:
55
- label: Acceptance criteria
56
- description: A checklist a reviewer can verify when this is done (include the tests).
57
- placeholder: |
58
- - [ ] ...
59
- - [ ] Tests
60
- validations:
61
- required: false
62
- - type: textarea
63
- id: open-questions
64
- attributes:
65
- label: Open questions
66
- description: Decisions a maintainer must make before this can be planned. Leave blank if none.
67
- validations:
68
- required: false
69
- - type: textarea
70
- id: related
71
- attributes:
72
- label: Related links
73
- description: Links to related issues, PRs, discussions, or docs. Leave blank if none.
74
- validations:
75
- required: false
1
+ name: Feature request
2
+ description: Propose a small improvement or new capability
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ This template is for small, well-scoped improvements a focused
9
+ enhancement, a missing convenience, a quality-of-life fix.
10
+
11
+ For large features, architecture changes, or cross-cutting work,
12
+ open a planning issue or an ADR instead.
13
+
14
+ Do **not** include real secrets or production data use placeholders.
15
+ - type: dropdown
16
+ id: scope
17
+ attributes:
18
+ label: Scope
19
+ description: How big is this change? If it doesn't fit Small or Medium, use a planning issue instead.
20
+ options:
21
+ - Small a single file or component, no refactoring
22
+ - Medium touches a few files or a feature area, may need minor refactoring
23
+ validations:
24
+ required: true
25
+ - type: textarea
26
+ id: current-behavior
27
+ attributes:
28
+ label: Current behavior
29
+ description: How does it work today? Describe the existing behavior or limitation.
30
+ validations:
31
+ required: true
32
+ - type: textarea
33
+ id: problem
34
+ attributes:
35
+ label: Problem / motivation
36
+ description: What user or business need does this address? Why is the current behavior a problem?
37
+ validations:
38
+ required: true
39
+ - type: textarea
40
+ id: proposal
41
+ attributes:
42
+ label: Proposed solution
43
+ description: What would you like to happen?
44
+ validations:
45
+ required: true
46
+ - type: textarea
47
+ id: alternatives
48
+ attributes:
49
+ label: Alternatives considered
50
+ validations:
51
+ required: false
52
+ - type: textarea
53
+ id: acceptance
54
+ attributes:
55
+ label: Acceptance criteria
56
+ description: A checklist a reviewer can verify when this is done (include the tests).
57
+ placeholder: |
58
+ - [ ] ...
59
+ - [ ] Tests
60
+ validations:
61
+ required: false
62
+ - type: textarea
63
+ id: open-questions
64
+ attributes:
65
+ label: Open questions
66
+ description: Decisions a maintainer must make before this can be planned. Leave blank if none.
67
+ validations:
68
+ required: false
69
+ - type: textarea
70
+ id: related
71
+ attributes:
72
+ label: Related links
73
+ description: Links to related issues, PRs, discussions, or docs. Leave blank if none.
74
+ validations:
75
+ required: false
@@ -1,30 +1,30 @@
1
- # Managed by @plainconceptsplatform/workflows. Source: loops/templates/release/github-release.yml. Update with `workflows update --force`; consumer edits may be overwritten.
2
- name: Publish GitHub release
3
-
4
- on:
5
- push:
6
- tags:
7
- - "v*"
8
-
9
- permissions:
10
- contents: write
11
-
12
- jobs:
13
- publish:
14
- name: Publish release
15
- runs-on: ubuntu-latest
16
- timeout-minutes: 10
17
- steps:
18
- - name: Create or update GitHub release
19
- env:
20
- GH_TOKEN: ${{ github.token }}
21
- TAG: ${{ github.ref_name }}
22
- shell: bash
23
- run: |
24
- set -euo pipefail
25
-
26
- if gh release view "$TAG" >/dev/null 2>&1; then
27
- gh release edit "$TAG" --title "$TAG" --generate-notes
28
- else
29
- gh release create "$TAG" --title "$TAG" --generate-notes
30
- fi
1
+ # Managed by @plainconceptsplatform/workflows. Source: loops/templates/release/github-release.yml. Update with `workflows update --force`; consumer edits may be overwritten.
2
+ name: Publish GitHub release
3
+
4
+ on:
5
+ push:
6
+ tags:
7
+ - "v*"
8
+
9
+ permissions:
10
+ contents: write
11
+
12
+ jobs:
13
+ publish:
14
+ name: Publish release
15
+ runs-on: ubuntu-latest
16
+ timeout-minutes: 10
17
+ steps:
18
+ - name: Create or update GitHub release
19
+ env:
20
+ GH_TOKEN: ${{ github.token }}
21
+ TAG: ${{ github.ref_name }}
22
+ shell: bash
23
+ run: |
24
+ set -euo pipefail
25
+
26
+ if gh release view "$TAG" >/dev/null 2>&1; then
27
+ gh release edit "$TAG" --title "$TAG" --generate-notes
28
+ else
29
+ gh release create "$TAG" --title "$TAG" --generate-notes
30
+ fi
@@ -541,6 +541,11 @@ timeout-minutes: 90
541
541
  ${{ env.VERIFY_COMMANDS }}
542
542
  ```
543
543
 
544
+ When `.opencode/scripts/check-diff.mjs` exists, also run
545
+ `node .opencode/scripts/check-diff.mjs`.
546
+ It must exit 0: delete the comments and tests it lists. The merge gate runs it too and does not
547
+ merge while it fails.
548
+
544
549
  7. Select one review outcome.
545
550
 
546
551
  - **implemented**: You made the requested change, verification passed, and you will propose
@@ -707,6 +707,12 @@ timeout-minutes: 180
707
707
 
708
708
  Never open a pull request that does not pass them.
709
709
 
710
+ When `.opencode/scripts/check-diff.mjs` exists, also run
711
+ `node .opencode/scripts/check-diff.mjs`
712
+ on both paths. It must exit 0. It holds the comments and tests you add to the size of the
713
+ change and makes you clean the files you touched; fix every line it lists. The merge gate
714
+ runs it again and does not merge while it fails.
715
+
710
716
  5. Do not touch `changelog.json`. The workflow records the change itself once the work is on
711
717
  the default branch. Every implement used to edit that one file, so two runs whose branches
712
718
  were cut before the other merged conflicted on it and failed to open a pull request with the
@@ -43,9 +43,16 @@ env:
43
43
  BLAST_HIGH_LINES: "800"
44
44
  BLAST_MEDIUM_FILES: "5"
45
45
  BLAST_MEDIUM_LINES: "200"
46
+ # Paths that change no runtime behaviour: tests, docs, specs, translations and generated
47
+ # migration code. They count toward neither size nor owner paths, so a feature's tests do not
48
+ # double its blast radius. Protected paths are still matched against every file.
49
+ BLAST_IGNORE_PATHS: '(^|/)([Tt]ests?|__tests__|__snapshots__|e2e)/|(^|/)[^/]+\.[A-Za-z]*Tests?/|\.(test|spec)\.[cm]?[jt]sx?$|\.snap$|\.feature$|(^|/)openspec/|\.md$|(^|/)evidence/|(^|/)(i18n|locales?|translations?)/[^/]*\.json$|\.Designer\.cs$|ModelSnapshot\.cs$'
46
50
  # Agent confidence below which the pull request goes to a human. The agent reports the number;
47
51
  # this decides what it means.
48
52
  CONFIDENCE_THRESHOLD: "0.8"
53
+ # Replay the verification plan when the gate hands the pull request to a person, so the
54
+ # reviewer sees the screenshots before deciding. "false" leaves evidence to the merge.
55
+ EVIDENCE_BEFORE_REVIEW: "true"
49
56
  WORKING_LABEL: bot-working
50
57
  IMPLEMENT_LABEL: implement
51
58
  REVIEW_LABEL: review
@@ -124,7 +131,9 @@ on:
124
131
  # this entry activation read needs.protected_changes.outputs.requires_review before
125
132
  # protected_changes had started; the value was '' and the clause was always true
126
133
  # (Pliny-Bot run 34042143350: activation finished 18 s before protected_changes began).
127
- needs: [protected_changes]
134
+ # code_rules is here for the same reason: the prompt prints its result and report, and the
135
+ # prompt is rendered in activation.
136
+ needs: [protected_changes, code_rules]
128
137
 
129
138
  # Rung 4. Router has classified the event; identify-gate-subject validates PR ownership,
130
139
  # resolves the closing issue, and confirms the CI verdict.
@@ -203,6 +212,8 @@ jobs:
203
212
  required_owners: ${{ steps.blast.outputs.required_owners }}
204
213
  files_changed: ${{ steps.blast.outputs.files_changed }}
205
214
  lines_changed: ${{ steps.blast.outputs.lines_changed }}
215
+ files_total: ${{ steps.blast.outputs.files_total }}
216
+ lines_total: ${{ steps.blast.outputs.lines_total }}
206
217
  owner_hit: ${{ steps.blast.outputs.owner_hit }}
207
218
  sensitive_hit: ${{ steps.blast.outputs.sensitive_hit }}
208
219
  # The decision, computed once. A protected path holds the merge for a human, but it must
@@ -229,6 +240,52 @@ jobs:
229
240
  high-lines: ${{ env.BLAST_HIGH_LINES }}
230
241
  medium-files: ${{ env.BLAST_MEDIUM_FILES }}
231
242
  medium-lines: ${{ env.BLAST_MEDIUM_LINES }}
243
+ ignore-paths: ${{ env.BLAST_IGNORE_PATHS }}
244
+
245
+ # Rung 4c. The comments and tests the change adds, measured by the harness's check-diff on the
246
+ # pull request head before any model reads it. Prose in the implement prompt did not hold bot
247
+ # pull requests to the guardrails: they added 27-63% comment lines in October 2026. `fail`
248
+ # stops an auto-merge in the validator; the agent is told to repair it like a CI failure.
249
+ # A repository without the script reports `absent` and is not held to it.
250
+ code_rules:
251
+ needs: subject
252
+ if: needs.subject.outputs.found == 'true'
253
+ runs-on: agents-arc
254
+ timeout-minutes: 10
255
+ permissions:
256
+ contents: read
257
+ outputs:
258
+ result: ${{ steps.check.outputs.result }}
259
+ report: ${{ steps.check.outputs.report }}
260
+ steps:
261
+ - name: Checkout the pull request
262
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
263
+ with:
264
+ ref: refs/pull/${{ needs.subject.outputs.pr }}/head
265
+ fetch-depth: 0
266
+ persist-credentials: false
267
+ - name: Check the comments and tests it adds
268
+ id: check
269
+ env:
270
+ BASE: origin/${{ github.event.repository.default_branch || 'main' }}
271
+ run: |
272
+ set -uo pipefail
273
+ if [ ! -f .opencode/scripts/check-diff.mjs ]; then
274
+ echo "result=absent" >> "$GITHUB_OUTPUT"
275
+ 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"
276
+ exit 0
277
+ fi
278
+ report=$(node .opencode/scripts/check-diff.mjs --base "$BASE" 2>&1)
279
+ code=$?
280
+ case "$code" in 0) result=pass ;; 1) result=fail ;; *) result=error ;; esac
281
+ delimiter="EOF_$(openssl rand -hex 8)"
282
+ {
283
+ echo "result=$result"
284
+ echo "report<<$delimiter"
285
+ printf '%s\n' "${report:0:8000}"
286
+ echo "$delimiter"
287
+ } >> "$GITHUB_OUTPUT"
288
+ printf '```\n%s\n```\n' "$report" >> "$GITHUB_STEP_SUMMARY"
232
289
 
233
290
  review_required:
234
291
  needs: [subject, protected_changes]
@@ -291,6 +348,18 @@ jobs:
291
348
  Required owners: `${{ needs.protected_changes.outputs.required_owners || 'none configured' }}`
292
349
 
293
350
  **Verdict:** owner-review
351
+ - name: Replay the verification plan for the owner
352
+ if: needs.protected_changes.outputs.holds_review == 'true' && env.EVIDENCE_BEFORE_REVIEW == 'true'
353
+ continue-on-error: true
354
+ env:
355
+ GH_TOKEN: ${{ steps.app-token.outputs.token }}
356
+ REPO: ${{ github.repository }}
357
+ PR: ${{ needs.subject.outputs.pr }}
358
+ run: |
359
+ set -euo pipefail
360
+ branch=$(gh api "repos/$REPO" --jq .default_branch)
361
+ gh api "repos/$REPO/actions/workflows/work-router.yml/dispatches" --method POST \
362
+ -f ref="$branch" -f "inputs[operation]=evidence" -f "inputs[pr-number]=$PR"
294
363
 
295
364
  reserve:
296
365
  needs: subject
@@ -340,7 +409,7 @@ jobs:
340
409
  Problems found in PR #${{ needs.subject.outputs.pr }}. ${{ steps.conflicts.outputs.has_conflicts == 'true' && 'Merge conflicts detected.' || 'CI failed.' }}
341
410
  Bot is working on fixing it.
342
411
  validate_output:
343
- needs: [activation, subject, protected_changes, agent, safe_outputs]
412
+ needs: [activation, subject, protected_changes, code_rules, agent, safe_outputs]
344
413
  if: >
345
414
  always() &&
346
415
  needs.agent.result == 'success' &&
@@ -374,6 +443,7 @@ jobs:
374
443
  protected-hit: ${{ needs.protected_changes.outputs.requires_review }}
375
444
  owner-hit: ${{ needs.protected_changes.outputs.owner_hit }}
376
445
  confidence-threshold: ${{ env.CONFIDENCE_THRESHOLD }}
446
+ code-rules: ${{ needs.code_rules.outputs.result }}
377
447
  conclude:
378
448
  needs: [activation, subject, protected_changes, agent, safe_outputs, validate_output]
379
449
  # `protected_changes.result == 'success'` is stated rather than relied on. GitHub skips a job
@@ -440,7 +510,7 @@ jobs:
440
510
  | Disposition | `${{ needs.validate_output.outputs.outcome }}` |
441
511
  | CI | ${{ needs.subject.outputs.conclusion }} |
442
512
  | Blast radius | ${{ needs.protected_changes.outputs.level }} |
443
- | Files / lines | ${{ needs.protected_changes.outputs.files_changed }} / ${{ needs.protected_changes.outputs.lines_changed }} |
513
+ | Files / lines | ${{ needs.protected_changes.outputs.files_changed }} / ${{ needs.protected_changes.outputs.lines_changed }} counted, ${{ needs.protected_changes.outputs.files_total }} / ${{ needs.protected_changes.outputs.lines_total }} in the diff |
444
514
  | Protected paths | ${{ needs.protected_changes.outputs.requires_review == 'true' && 'yes' || 'no' }} |
445
515
  | Owner paths | ${{ needs.protected_changes.outputs.owner_hit == 'true' && 'yes' || 'no' }} |
446
516
  ${{ needs.validate_output.outputs.outcome == 'owner-review'
@@ -453,6 +523,7 @@ jobs:
453
523
  ```
454
524
 
455
525
  Findings and verification on the linked issue: #${{ needs.subject.outputs.issue }}. [View this workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
526
+ ${{ 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.' || '' }}
456
527
  - name: Merge approved pull request
457
528
  if: needs.validate_output.outputs.outcome == 'auto-merge'
458
529
  env:
@@ -512,6 +583,20 @@ jobs:
512
583
  token: ${{ steps.app-token.outputs.token }}
513
584
  issue-number: ${{ needs.subject.outputs.issue }}
514
585
  labels: ${{ env.WORKING_LABEL }}
586
+ # A person decides this one, so the screenshots come before the decision, in a router run of
587
+ # their own outside the belt. Never on auto-merge: that dispatch would race the merge.
588
+ - name: Replay the verification plan for the reviewer
589
+ if: env.EVIDENCE_BEFORE_REVIEW == 'true' && contains(fromJson('["human-review","owner-review"]'), needs.validate_output.outputs.outcome)
590
+ continue-on-error: true
591
+ env:
592
+ GH_TOKEN: ${{ steps.app-token.outputs.token }}
593
+ REPO: ${{ github.repository }}
594
+ PR: ${{ needs.subject.outputs.pr }}
595
+ run: |
596
+ set -euo pipefail
597
+ branch=$(gh api "repos/$REPO" --jq .default_branch)
598
+ gh api "repos/$REPO/actions/workflows/work-router.yml/dispatches" --method POST \
599
+ -f ref="$branch" -f "inputs[operation]=evidence" -f "inputs[pr-number]=$PR"
515
600
  - name: Clear merged issue labels
516
601
  if: needs.validate_output.outputs.outcome == 'auto-merge'
517
602
  uses: ./.github/actions/remove-issue-labels
@@ -817,6 +902,18 @@ timeout-minutes: 120
817
902
  ${{ needs.protected_changes.outputs.signals }}
818
903
  ```
819
904
 
905
+ **Comments and tests (`check-diff`): `${{ needs.code_rules.outputs.result }}`**
906
+
907
+ ```
908
+ ${{ needs.code_rules.outputs.report }}
909
+ ```
910
+
911
+ When that is `fail`, repairing it is part of this run whatever CI concluded: delete the
912
+ comments and tests it lists, leave every file it names with no slop, run
913
+ `node .opencode/scripts/check-diff.mjs`
914
+ until it exits 0, then verify, push and report `remediated` as in step 6. An `assessed`
915
+ verdict while it fails blocks the pull request.
916
+
820
917
  - **success** → step 4, then step 5 (review the change).
821
918
  - **failure** → step 4, then step 6 (CI remediation).
822
919
  - **action_required, cancelled, timed_out, or anything else** → CI did not produce a usable