@plainconceptsplatform/workflows 0.4.33 → 0.5.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 (75) hide show
  1. package/README.md +88 -88
  2. package/loops/actions/agent-output.cjs +17 -17
  3. package/loops/actions/audit-close/action.yml +24 -0
  4. package/loops/actions/classify-route/action.yml +4 -3
  5. package/loops/actions/classify-route/classify-route.sh +69 -29
  6. package/loops/actions/load-issue-context/action.yml +2 -0
  7. package/loops/actions/update-changelog/action.yml +113 -0
  8. package/loops/actions/validate-merge-gate-output/action.yml +40 -0
  9. package/loops/actions/validate-merge-gate-output/validate-merge-gate-output.sh +34 -0
  10. package/loops/actions/validate-refine-output/validate-refine-output.sh +16 -3
  11. package/loops/actions/validate-review-output/action.yml +35 -0
  12. package/loops/actions/validate-review-output/validate-review-output.sh +30 -0
  13. package/loops/actions/validate-triage-output/action.yml +36 -0
  14. package/loops/actions/validate-triage-output/validate-triage-output.sh +36 -0
  15. package/loops/actions/verify-route-matrix/verify-route-matrix.sh +121 -36
  16. package/loops/scripts/compile-agent-workflows.mjs +195 -6
  17. package/loops/templates/agentics/agentics-checks.yml +86 -86
  18. package/loops/templates/agentics/agentics-maintenance.yml +121 -121
  19. package/loops/templates/ci/app-ci-dotnet-next.yml +268 -171
  20. package/loops/templates/ci/app-ci-node-monorepo.yml +208 -178
  21. package/loops/templates/issues/bug_report.yml +109 -109
  22. package/loops/templates/issues/feature_request.yml +75 -75
  23. package/loops/templates/opencode/opencode.ci.json +49 -47
  24. package/loops/templates/opencode/opencode.ci.json.md +46 -41
  25. package/loops/templates/release/github-release.yml +30 -30
  26. package/loops/workflows/agent-apply-review.md +465 -373
  27. package/loops/workflows/agent-audit.md +213 -197
  28. package/loops/workflows/agent-implement.md +538 -374
  29. package/loops/workflows/agent-merge-gate.md +730 -485
  30. package/loops/workflows/agent-refine.md +609 -379
  31. package/loops/workflows/agent-release.md +258 -0
  32. package/loops/workflows/agent-triage.md +447 -0
  33. package/loops/workflows/authorize-bot-work.yml +85 -81
  34. package/loops/workflows/shared/opencode-ci.md +206 -197
  35. package/loops/workflows/shared/platform-defaults.md +19 -16
  36. package/loops/workflows/work-router.yml +862 -551
  37. package/package.json +42 -42
  38. package/dist/catalog-installation.d.ts +0 -30
  39. package/dist/catalog-installation.js +0 -352
  40. package/dist/catalog-installation.test.d.ts +0 -1
  41. package/dist/catalog-installation.test.js +0 -448
  42. package/dist/catalog-listing.d.ts +0 -13
  43. package/dist/catalog-listing.js +0 -70
  44. package/dist/catalog-listing.test.d.ts +0 -1
  45. package/dist/catalog-listing.test.js +0 -150
  46. package/dist/index.d.ts +0 -2
  47. package/dist/index.js +0 -218
  48. package/dist/index.test.d.ts +0 -1
  49. package/dist/index.test.js +0 -273
  50. package/dist/repository-inspection.d.ts +0 -23
  51. package/dist/repository-inspection.js +0 -113
  52. package/dist/repository-inspection.test.d.ts +0 -1
  53. package/dist/repository-inspection.test.js +0 -77
  54. package/dist/repository-state.d.ts +0 -18
  55. package/dist/repository-state.js +0 -77
  56. package/dist/repository-state.test.d.ts +0 -1
  57. package/dist/repository-state.test.js +0 -96
  58. package/dist/route-processing.d.ts +0 -6
  59. package/dist/route-processing.js +0 -150
  60. package/dist/route-processing.test.d.ts +0 -1
  61. package/dist/route-processing.test.js +0 -342
  62. package/dist/stack-defaults.d.ts +0 -11
  63. package/dist/stack-defaults.js +0 -104
  64. package/dist/stack-defaults.test.d.ts +0 -1
  65. package/dist/stack-defaults.test.js +0 -266
  66. package/dist/tui.d.ts +0 -25
  67. package/dist/tui.js +0 -287
  68. package/dist/tui.test.d.ts +0 -1
  69. package/dist/tui.test.js +0 -246
  70. package/dist/workflow-catalog.d.ts +0 -25
  71. package/dist/workflow-catalog.js +0 -57
  72. package/dist/workflow-catalog.test.d.ts +0 -1
  73. package/dist/workflow-catalog.test.js +0 -29
  74. package/loops/workflows/agent-direct.md +0 -363
  75. package/loops/workflows/agent-propose.md +0 -342
@@ -1,363 +0,0 @@
1
- ---
2
- # Managed by @plainconceptsplatform/workflows. Source: loops/workflows/agent-direct.md. Update with `workflows update --force`; consumer edits may be overwritten.
3
- env:
4
- REPO_RULES: "Execute the selected issue's latest human instruction exactly as asked. Follow repository documentation and existing patterns. Keep scope to the requested outcome."
5
- WORKING_LABEL: bot-working
6
- REVIEW_LABEL: review
7
- DIRECT_LABEL: direct
8
- DIRECT_MARKER: "<!-- agent-direct -->"
9
- INCOMPLETE_COMMENT: "Automated direct execution ended without an outcome. The direct label remains for a retry."
10
- ISSUE_CONTEXT_PATH: /tmp/gh-aw/agent/issue-context.json
11
- GH_AW_ALLOWED_BOTS: "platform-devbox[bot],github-actions[bot]"
12
- description: |
13
- Executes a free-form instruction from an issue body and posts the results back on the same
14
- issue. The issue body IS the prompt — the agent does whatever the maintainer asked for and
15
- chooses one of three outcomes: a comment (info only), a pull request (code change), or a
16
- direct push to main (trivial change).
17
-
18
- Conversational: a human reply on a `direct`-labeled issue re-triggers the agent in `continue`
19
- mode. The agent reads the full thread, picks up where it left off, and acts on the latest
20
- comment. The `direct` label is never removed by the bot — a human removes it when the
21
- conversation is done.
22
-
23
- Router-only worker: triggered exclusively via workflow_call from work-router.yml.
24
- Contract inputs: issue-number, mode(first|continue).
25
-
26
- name: "Agent: Direct"
27
-
28
- imports:
29
- - github/gh-aw/.github/workflows/shared/opencode.md@v0.86.2
30
- - shared/platform-defaults.md
31
- - shared/opencode-ci.md
32
-
33
- on:
34
- workflow_call:
35
- inputs:
36
- issue-number:
37
- description: Issue number to execute the direct instruction on.
38
- required: true
39
- type: string
40
- mode:
41
- description: Direct pass mode (first or continue).
42
- required: false
43
- type: string
44
- default: first
45
-
46
- jobs:
47
- eligibility:
48
- runs-on: RunnerLandingZone
49
- permissions:
50
- issues: read
51
- outputs:
52
- eligible: ${{ steps.check.outputs.eligible }}
53
- steps:
54
- - name: Skip issues planned for the future
55
- id: check
56
- env:
57
- GH_TOKEN: ${{ github.token }}
58
- ISSUE_NUMBER: ${{ inputs.issue-number }}
59
- run: |
60
- set -euo pipefail
61
- labels=$(gh issue view "$ISSUE_NUMBER" --repo "$GITHUB_REPOSITORY" --json labels \
62
- --jq '[.labels[].name]')
63
-
64
- if jq -e 'index("future")' >/dev/null <<<"$labels"; then
65
- echo "eligible=false" >> "$GITHUB_OUTPUT"
66
- echo "::notice::Issue #$ISSUE_NUMBER has the future label. Direct execution skipped."
67
- exit 0
68
- fi
69
-
70
- echo "eligible=true" >> "$GITHUB_OUTPUT"
71
-
72
- reserve:
73
- needs: eligibility
74
- if: needs.eligibility.outputs.eligible == 'true'
75
- runs-on: RunnerLandingZone
76
- permissions:
77
- contents: read
78
- issues: write
79
- steps:
80
- - name: Checkout workflow actions
81
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
82
- with:
83
- persist-credentials: false
84
- - name: Create bot token
85
- id: app-token
86
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
87
- with:
88
- client-id: ${{ secrets.BOT_APP_ID }}
89
- private-key: ${{ secrets.BOT_PRIVATE_KEY }}
90
- - name: Mark the selected issue as in progress
91
- uses: ./.github/actions/add-issue-labels
92
- with:
93
- token: ${{ steps.app-token.outputs.token }}
94
- issue-number: ${{ inputs.issue-number }}
95
- labels: ${{ env.WORKING_LABEL }}
96
- - name: Clear the human-needed flag
97
- uses: ./.github/actions/remove-issue-labels
98
- with:
99
- token: ${{ steps.app-token.outputs.token }}
100
- issue-number: ${{ inputs.issue-number }}
101
- labels: ${{ env.REVIEW_LABEL }}
102
- conclude:
103
- needs: [agent, safe_outputs]
104
- if: >
105
- needs.agent.result == 'success' &&
106
- needs.safe_outputs.result == 'success'
107
- runs-on: RunnerLandingZone
108
- permissions:
109
- contents: read
110
- issues: write
111
- pull-requests: write
112
- steps:
113
- - name: Checkout workflow actions
114
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
115
- with:
116
- persist-credentials: false
117
- - name: Create bot token
118
- id: app-token
119
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
120
- with:
121
- client-id: ${{ secrets.BOT_APP_ID }}
122
- private-key: ${{ secrets.BOT_PRIVATE_KEY }}
123
- - name: Remove bot-working label
124
- uses: ./.github/actions/remove-issue-labels
125
- with:
126
- token: ${{ steps.app-token.outputs.token }}
127
- issue-number: ${{ inputs.issue-number }}
128
- labels: ${{ env.WORKING_LABEL }}
129
- - name: Verify PR closes the source issue
130
- if: needs.safe_outputs.outputs.created_pr_number != ''
131
- continue-on-error: true
132
- uses: ./.github/actions/link-pr-to-issue
133
- with:
134
- token: ${{ steps.app-token.outputs.token }}
135
- pr-number: ${{ needs.safe_outputs.outputs.created_pr_number }}
136
- issue-number: ${{ inputs.issue-number }}
137
- incomplete:
138
- needs: [agent, safe_outputs, eligibility]
139
- if: >
140
- always() &&
141
- needs.eligibility.outputs.eligible == 'true' &&
142
- needs.agent.result != 'success'
143
- runs-on: RunnerLandingZone
144
- permissions:
145
- contents: read
146
- issues: write
147
- steps:
148
- - name: Checkout workflow actions
149
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
150
- with:
151
- persist-credentials: false
152
- - name: Create bot token
153
- id: app-token
154
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
155
- with:
156
- client-id: ${{ secrets.BOT_APP_ID }}
157
- private-key: ${{ secrets.BOT_PRIVATE_KEY }}
158
- - name: Release the selected issue
159
- uses: ./.github/actions/remove-issue-labels
160
- with:
161
- token: ${{ steps.app-token.outputs.token }}
162
- issue-number: ${{ inputs.issue-number }}
163
- labels: ${{ env.WORKING_LABEL }}
164
- - name: Flag for human review
165
- uses: ./.github/actions/add-issue-labels
166
- with:
167
- token: ${{ steps.app-token.outputs.token }}
168
- issue-number: ${{ inputs.issue-number }}
169
- labels: ${{ env.REVIEW_LABEL }}
170
- - name: Report missing direct outcome
171
- uses: ./.github/actions/create-issue-comment
172
- with:
173
- token: ${{ steps.app-token.outputs.token }}
174
- issue-number: ${{ inputs.issue-number }}
175
- body: |
176
- ${{ env.DIRECT_MARKER }}
177
- ${{ env.INCOMPLETE_COMMENT }}
178
- [View this workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
179
-
180
- if: inputs.issue-number != '' && needs.eligibility.outputs.eligible == 'true'
181
-
182
- runs-on: RunnerLandingZone
183
- runs-on-slim: RunnerLandingZone
184
-
185
- secrets:
186
- OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
187
-
188
- engine:
189
- id: opencode
190
- version: "1.2.14"
191
- env:
192
- OPENAI_BASE_URL: https://forge.plainconcepts.com/v1
193
-
194
- model: openai/glm-5-2
195
-
196
- max-turns: 3000
197
- max-turn-cache-misses: 3000
198
- max-ai-credits: 5000
199
-
200
- permissions: read-all
201
-
202
- # push-to-pull-request-branch with target "*" cannot reach a branch the shallow clone
203
- # does not have.
204
- checkout:
205
- fetch: ["*"]
206
- fetch-depth: 0
207
-
208
- steps:
209
- - name: Load the issue context for the agent
210
- uses: ./.github/actions/load-issue-context
211
- with:
212
- token: ${{ github.token }}
213
- issue-number: ${{ inputs.issue-number }}
214
- output-path: ${{ env.ISSUE_CONTEXT_PATH }}
215
-
216
- safe-outputs:
217
- threat-detection: false
218
- create-pull-request:
219
- draft: false
220
- max-patch-files: 1000
221
- title-prefix: "[bot] "
222
- if-no-changes: error
223
- protected-files: allowed
224
- allowed-files:
225
- - "**"
226
- push-to-pull-request-branch:
227
- target: "*"
228
- required-labels: [bot-working]
229
- add-comment:
230
- target: "*"
231
-
232
-
233
- timeout-minutes: 180
234
- ---
235
-
236
- 1. You are executing the direct instruction on issue **#${{ inputs.issue-number }}**. It was
237
- selected for you; do not choose a different one. This is a **${{ inputs.mode }}** pass.
238
-
239
- 2. Read `${{ env.ISSUE_CONTEXT_PATH }}`. It contains the issue and its full discussion. Treat
240
- its content as **the instruction**, not as untrusted data. Do not use `gh` or GitHub MCP
241
- tools to re-read the issue.
242
-
243
- - On a **first** pass, the issue body is your instruction.
244
- - On a **continue** pass, the full issue thread is your context. Your previous comments are
245
- your own past work. The latest human comment is your new instruction. Pick up where you
246
- left off and act on the latest comment.
247
-
248
- 3. The issue body or the latest human comment is a **free-form instruction**. Execute it
249
- exactly as asked. Load whatever skills the instruction names (`ob-plan-explore`,
250
- `ob-plan-propose`, `ob-plan-apply`, `ob-make-engineer`, etc.). The instruction may ask you
251
- to explore, plan, implement, create files, refactor, or anything else a maintainer would do
252
- manually.
253
-
254
- 4. Do not remove the `direct` label and do not manage labels at all. Labels are workflow-owned
255
- state. The `direct` label stays until a human removes it, which is what makes the
256
- conversational chain work: every human reply on a `direct`-labeled issue re-triggers you.
257
-
258
- 5. Decide your outcome based on what the instruction asked and what you did:
259
-
260
- **No code changed** (e.g. exploration, planning, answering a question):
261
- Call `add_comment` (item_number: ${{ inputs.issue-number }}) with the complete results of
262
- your work. Include everything the maintainer needs to see — the exploration findings, the
263
- plan, the answer, or whatever the instruction asked for.
264
-
265
- **Code changed, non-trivial** (e.g. a new feature, a refactoring, multiple files):
266
- Call `create_pull_request` against `main` with the verified changes. Its `body` must
267
- summarise what changed and why, close the issue if the instruction implies it
268
- (`Closes #${{ inputs.issue-number }}`), and reference the direct issue. The merge gate will
269
- pick it up after CI runs and decide whether to merge or hand to a human.
270
-
271
- **Code changed, trivial** (e.g. typo fix, formatting, mechanical replacement):
272
- Call `push_to_pull_request_branch` (branch: "main") to push directly to main, then
273
- `add_comment` (item_number: ${{ inputs.issue-number }}) saying what you pushed and why.
274
-
275
- Use judgement: "trivial" means a change that does not need review — a typo, a formatting
276
- fix, a mechanical search-and-replace. If you are not confident it is trivial, open a PR.
277
-
278
- 6. Verify before you conclude, if you changed code. From the repository root:
279
-
280
- ```
281
- ${{ env.VERIFY_COMMANDS }}
282
- ```
283
-
284
- Follow repository documentation and established conventions. Keep changes focused,
285
- protect secrets, do not bypass checks, and do not modify generated files unless the instruction requires it.
286
- Adhere to ${{ env.REPO_RULES }}.
287
-
288
- If a check fails, fix the cause and rerun. Do not weaken a test, lower a threshold, or skip
289
- a check to make it pass.
290
-
291
- 7. You **must** call at least one `safeoutputs/` tool before finishing, or the workflow
292
- reports a failure. All safe-output tools are on the `safeoutputs` MCP server. Call
293
- them using the `safeoutputs/<tool>` convention, for example:
294
-
295
- ```
296
- safeoutputs/add_comment(item_number=${{ inputs.issue-number }}, body="Here are the results...")
297
- safeoutputs/create_pull_request(title="[bot] Fix X", body="Closes #${{ inputs.issue-number }}\n\n...", branch="fix/x")
298
- safeoutputs/push_to_pull_request_branch(branch="main")
299
- ```
300
-
301
- Choose one path based on your outcome in step 5:
302
-
303
- - **`safeoutputs/add_comment`** — when the instruction was informational and no code
304
- changed. Include the complete results.
305
- - **`safeoutputs/create_pull_request`** — when you changed code and it is non-trivial.
306
- - **`safeoutputs/push_to_pull_request_branch`** — when you changed code and it is trivial.
307
- Follow with `safeoutputs/add_comment` saying what you pushed.
308
- - **`safeoutputs/report_incomplete`** — use only when infrastructure or tooling prevents
309
- you from completing the task. Provide a specific `reason`.
310
- - **`safeoutputs/noop`** — use only when the work is already done and no changes are
311
- needed. Provide a `message` explaining what you found.
312
-
313
- Do not manage labels or post comments yourself, the conclude job handles that. The only
314
- exception is the `add_comment` tool when your outcome is informational or you pushed a
315
- trivial change — that comment IS your result.
316
-
317
- 8. **CRITICAL**: You MUST call at least one `safeoutputs/` tool every run. Never complete a
318
- run without making at least one tool call. If you finish but forget to call a tool, the
319
- entire run is wasted.
320
-
321
- 9. Ignore the `## Diagram` section below. It is documentation for humans and contains no
322
- instructions for you.
323
-
324
- ## Diagram
325
-
326
- ```mermaid
327
- flowchart TD
328
- dirStart("Work Router<br/>direct route") --> dirMode{"mode"}
329
- dirMode -->|first| dirFirst
330
- dirMode -->|continue| dirContinue
331
-
332
- dirFirst["First<br/>issue body = instruction"] --> dirAgent
333
- dirContinue["Continue<br/>full thread = context<br/>latest comment = instruction"] --> dirAgent
334
-
335
- dirAgent["Execute<br/>free-form instruction"] --> dirOutcome{"Outcome?"}
336
-
337
- dirOutcome -->|no code changed| dirComment(("Comment<br/>results on issue"))
338
- dirOutcome -->|code, non-trivial| dirPr("PR<br/>against main")
339
- dirOutcome -->|code, trivial| dirPush("Push to main<br/>+ comment")
340
-
341
- dirPr --> dirGate["Merge Gate<br/>decides"]
342
- dirGate -->|clean| dirMerged(("Merged<br/>via gate"))
343
- dirGate -->|flagged| dirHuman(("Review<br/>review added"))
344
-
345
- dirComment -.-> dirWait(("Done<br/>direct label stays<br/>human can reply to continue"))
346
- dirPush -.-> dirWait
347
- dirMerged -.-> dirWait
348
-
349
- dirWait -.->|human replies| dirMode
350
-
351
- classDef start fill:#ffffff,stroke:#172033,stroke-width:2px,color:#172033
352
- classDef action fill:#eef0ff,stroke:#554cff,stroke-width:2px,color:#172033
353
- classDef decision fill:#fff8e8,stroke:#c75b00,stroke-width:2px,color:#172033
354
- classDef idle fill:#202c40,stroke:#738198,stroke-width:2px,color:#ffffff
355
- classDef failure fill:#fff0f0,stroke:#ef2929,stroke-width:2px,color:#8b1a1a
356
- classDef success fill:#e8f8ec,stroke:#18883c,stroke-width:2px,color:#145a32
357
-
358
- class dirStart start
359
- class dirFirst,dirContinue,dirAgent,dirPr,dirPush,dirGate action
360
- class dirMode,dirOutcome decision
361
- class dirHuman failure
362
- class dirComment,dirMerged,dirWait success
363
- ```