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