@plainconceptsplatform/workflows 0.6.1 → 0.16.2

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 (58) hide show
  1. package/README.md +107 -88
  2. package/dist/catalog-installation.d.ts +39 -2
  3. package/dist/catalog-installation.js +172 -109
  4. package/dist/index.js +128 -73
  5. package/dist/package-baseline.d.ts +25 -0
  6. package/dist/package-baseline.js +138 -0
  7. package/dist/route-processing.d.ts +0 -2
  8. package/dist/route-processing.js +22 -91
  9. package/dist/stack-defaults.js +18 -12
  10. package/dist/tui.js +27 -43
  11. package/dist/worker-env.d.ts +46 -0
  12. package/dist/worker-env.js +179 -0
  13. package/dist/workflow-catalog.d.ts +4 -2
  14. package/dist/workflow-catalog.js +5 -3
  15. package/loops/actions/add-issue-labels/action.yml +20 -0
  16. package/loops/actions/audit-close/action.yml +180 -128
  17. package/loops/actions/classify-route/classify-route.sh +8 -2
  18. package/loops/actions/housekeeping/action.yml +251 -0
  19. package/loops/actions/merge-agent-pr/action.yml +13 -0
  20. package/loops/actions/report-workflow-errors/action.yml +414 -0
  21. package/loops/actions/validate-merge-gate-output/validate-merge-gate-output.sh +13 -1
  22. package/loops/actions/validate-triage-output/action.yml +1 -1
  23. package/loops/actions/validate-triage-output/validate-triage-output.sh +9 -5
  24. package/loops/actions/verify-composite-actions/verify-composite-actions.sh +53 -0
  25. package/loops/actions/verify-route-matrix/verify-route-matrix.sh +911 -170
  26. package/loops/templates/agentics/agentics-error-report.yml +98 -0
  27. package/loops/templates/opencode/opencode.ci.json +1 -1
  28. package/loops/workflows/agent-apply-review.md +438 -469
  29. package/loops/workflows/agent-audit.md +200 -213
  30. package/loops/workflows/agent-implement.md +591 -640
  31. package/loops/workflows/agent-merge-gate.md +826 -844
  32. package/loops/workflows/agent-refine.md +590 -633
  33. package/loops/workflows/agent-release.md +244 -258
  34. package/loops/workflows/agent-triage.md +476 -447
  35. package/loops/workflows/authorize-bot-work.yml +26 -6
  36. package/loops/workflows/shared/platform-defaults.md +18 -1
  37. package/loops/workflows/work-router.yml +1185 -1038
  38. package/package.json +9 -8
  39. package/dist/action-validation.test.d.ts +0 -1
  40. package/dist/action-validation.test.js +0 -87
  41. package/dist/catalog-installation.test.d.ts +0 -1
  42. package/dist/catalog-installation.test.js +0 -485
  43. package/dist/catalog-listing.test.d.ts +0 -1
  44. package/dist/catalog-listing.test.js +0 -150
  45. package/dist/index.test.d.ts +0 -1
  46. package/dist/index.test.js +0 -273
  47. package/dist/repository-inspection.test.d.ts +0 -1
  48. package/dist/repository-inspection.test.js +0 -77
  49. package/dist/route-processing.test.d.ts +0 -1
  50. package/dist/route-processing.test.js +0 -283
  51. package/dist/stack-defaults.test.d.ts +0 -1
  52. package/dist/stack-defaults.test.js +0 -266
  53. package/dist/tui.test.d.ts +0 -1
  54. package/dist/tui.test.js +0 -249
  55. package/dist/workflow-catalog.test.d.ts +0 -1
  56. package/dist/workflow-catalog.test.js +0 -29
  57. package/loops/actions/stale-recovery/action.yml +0 -288
  58. package/loops/actions/update-changelog/action.yml +0 -113
@@ -1,258 +1,244 @@
1
- ---
2
- # Managed by @plainconceptsplatform/workflows. Source: loops/workflows/agent-release.md. Update with `workflows update --force`; consumer edits may be overwritten.
3
- env:
4
- GIT_AUTHOR_NAME: "github-actions[bot]"
5
- GIT_AUTHOR_EMAIL: "github-actions[bot]@users.noreply.github.com"
6
- GIT_COMMITTER_NAME: "github-actions[bot]"
7
- GIT_COMMITTER_EMAIL: "github-actions[bot]@users.noreply.github.com"
8
- description: |
9
- Generates release notes from the commit log and creates a tagged GitHub Release.
10
- The agent writes human-readable release notes; every other step (version bump,
11
- commit, tag, push, release creation) is deterministic.
12
-
13
- Router-only worker: triggered exclusively via workflow_call from work-router.yml.
14
- Contract input: version-bump(patch|minor|major|auto).
15
-
16
- name: "Agent: Release"
17
-
18
- imports:
19
- - github/gh-aw/.github/workflows/shared/opencode.md@v0.87.5
20
- - shared/platform-defaults.md
21
- - shared/opencode-ci.md
22
-
23
- on:
24
- workflow_call:
25
- inputs:
26
- version-bump:
27
- description: "Version bump strategy: patch, minor, major, or auto"
28
- required: false
29
- type: string
30
- default: "auto"
31
-
32
- runs-on: agents-arc
33
- runs-on-slim: agents-arc
34
-
35
- secrets:
36
- OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
37
-
38
- engine:
39
- id: opencode
40
- version: "1.2.14"
41
- env:
42
- OPENAI_BASE_URL: https://forge.plainconcepts.com/v1
43
-
44
- model: openai/glm-5-3
45
-
46
- max-turns: 100
47
- max-turn-cache-misses: 3000
48
- max-ai-credits: 2000
49
-
50
- permissions: read-all
51
-
52
- checkout:
53
- fetch: ["*"]
54
- fetch-depth: 0
55
-
56
- steps:
57
- - name: Prepare release context
58
- env:
59
- GH_TOKEN: ${{ github.token }}
60
- REPO: ${{ github.repository }}
61
- run: |
62
- set -euo pipefail
63
- mkdir -p /tmp/gh-aw/agent
64
-
65
- last_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
66
- if [ -n "$last_tag" ]; then
67
- git log --oneline --no-decorate "${last_tag}..HEAD" > /tmp/gh-aw/agent/git-log.txt
68
- else
69
- git log --oneline --no-decorate -50 > /tmp/gh-aw/agent/git-log.txt
70
- fi
71
-
72
- version=$(node -p "require('./package.json').version" 2>/dev/null || echo "0.0.0")
73
- echo "$version" > /tmp/gh-aw/agent/current-version.txt
74
-
75
- echo "Last tag: ${last_tag:-none}"
76
- echo "Current version: $version"
77
-
78
- safe-outputs:
79
- report-failure-as-issue: false
80
- threat-detection: false
81
- noop:
82
- max: 1
83
-
84
- timeout-minutes: 30
85
-
86
- jobs:
87
- conclude:
88
- needs: [activation, agent, safe_outputs]
89
- if: >
90
- always() &&
91
- needs.agent.result == 'success' &&
92
- needs.safe_outputs.result == 'success'
93
- runs-on: agents-arc
94
- permissions:
95
- contents: write
96
- steps:
97
- - name: Download agent output artifact
98
- id: download-agent-output
99
- continue-on-error: true
100
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
101
- with:
102
- pattern: "{${{ needs.activation.outputs.artifact_prefix }}agent,${{ needs.activation.outputs.artifact_prefix }}agent-output-fallback}"
103
- merge-multiple: true
104
- path: /tmp/gh-aw/
105
- - name: Checkout repository
106
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
107
- with:
108
- token: ${{ github.token }}
109
- fetch-depth: 0
110
- - name: Read release notes and determine version
111
- id: release
112
- env:
113
- VERSION_BUMP: ${{ inputs.version-bump }}
114
- run: |
115
- set -euo pipefail
116
-
117
- notes="/tmp/gh-aw/agent/release-notes.md"
118
- if [ ! -f "$notes" ]; then
119
- echo "::error::Agent did not write release-notes.md"
120
- exit 1
121
- fi
122
-
123
- current=$(node -p "require('./package.json').version" 2>/dev/null || echo "0.0.0")
124
- echo "current_version=$current" >> "$GITHUB_OUTPUT"
125
-
126
- # Determine the version bump
127
- bump="$VERSION_BUMP"
128
- if [ "$bump" = "auto" ]; then
129
- if grep -qiE 'BREAKING CHANGE' "$notes" || grep -qE '\w+\(!:' /tmp/gh-aw/agent/git-log.txt; then
130
- bump="major"
131
- elif grep -qE '^feat(\(.+\))?:' /tmp/gh-aw/agent/git-log.txt; then
132
- bump="minor"
133
- else
134
- bump="patch"
135
- fi
136
- fi
137
-
138
- # Semver bump
139
- IFS='.' read -r major minor patch <<< "$current"
140
- case "$bump" in
141
- major) major=$((major + 1)); minor=0; patch=0 ;;
142
- minor) minor=$((minor + 1)); patch=0 ;;
143
- patch) patch=$((patch + 1)) ;;
144
- *) echo "::error::Unknown version-bump: $bump"; exit 1 ;;
145
- esac
146
- new_version="${major}.${minor}.${patch}"
147
- echo "new_version=$new_version" >> "$GITHUB_OUTPUT"
148
- echo "Determined version: $current -> $new_version (bump: $bump)"
149
-
150
- # Copy notes to a clean location the release step can read
151
- cp "$notes" /tmp/release-notes.md
152
- - name: Bump version in package.json
153
- env:
154
- NEW_VERSION: ${{ steps.release.outputs.new_version }}
155
- run: |
156
- set -euo pipefail
157
- node -e "
158
- const fs = require('fs');
159
- for (const file of ['package.json', 'cli/package.json']) {
160
- if (fs.existsSync(file)) {
161
- const pkg = JSON.parse(fs.readFileSync(file, 'utf8'));
162
- pkg.version = process.env.NEW_VERSION;
163
- fs.writeFileSync(file, JSON.stringify(pkg, null, 2) + '\n');
164
- console.log('Bumped ' + file + ' to ' + process.env.NEW_VERSION);
165
- }
166
- }
167
- "
168
- - name: Commit, tag, and push
169
- env:
170
- NEW_VERSION: ${{ steps.release.outputs.new_version }}
171
- GH_TOKEN: ${{ github.token }}
172
- run: |
173
- set -euo pipefail
174
- git config user.name "github-actions[bot]"
175
- git config user.email "github-actions[bot]@users.noreply.github.com"
176
- git add package.json
177
- [ -f cli/package.json ] && git add cli/package.json
178
- git commit -m "chore(release): v${NEW_VERSION}"
179
- git tag "v${NEW_VERSION}"
180
- git push
181
- git push --tags
182
- echo "Tagged v${NEW_VERSION} and pushed."
183
- - name: Create GitHub Release
184
- env:
185
- NEW_VERSION: ${{ steps.release.outputs.new_version }}
186
- GH_TOKEN: ${{ github.token }}
187
- run: |
188
- set -euo pipefail
189
- gh release create "v${NEW_VERSION}" \
190
- --repo "$GITHUB_REPOSITORY" \
191
- --title "v${NEW_VERSION}" \
192
- --notes-file /tmp/release-notes.md
193
- echo "GitHub Release v${NEW_VERSION} created."
194
-
195
- incomplete:
196
- needs: [agent, safe_outputs]
197
- if: >
198
- always() &&
199
- (needs.agent.result != 'success' || needs.safe_outputs.result != 'success')
200
- runs-on: agents-arc
201
- permissions:
202
- contents: read
203
- steps:
204
- - name: Report release failure
205
- run: |
206
- echo "::error::Release agent did not complete successfully."
207
- echo "The release was not created. Check the agent logs."
208
- exit 1
209
-
210
- ---
211
-
212
- 1. Read `/tmp/gh-aw/agent/git-log.txt`. It contains the commit log since the last
213
- tag (or the last 50 commits if no tag exists).
214
-
215
- 2. Read `/tmp/gh-aw/agent/current-version.txt` for the current version.
216
-
217
- 3. Categorize commits by conventional-commit prefix:
218
- - `feat:` / `feat(scope):` → Features
219
- - `fix:` / `fix(scope):` → Bug Fixes
220
- - `chore:` / `chore(scope):` → Maintenance
221
- - `docs:` → Documentation
222
- - `refactor:` → Refactoring
223
- - `perf:` → Performance
224
- - Any `BREAKING CHANGE` footer or `!:` prefix → Breaking Changes (top of the notes)
225
-
226
- 4. Write structured release notes in markdown to `/tmp/gh-aw/agent/release-notes.md`.
227
- Format:
228
- - A `## What's Changed` heading
229
- - Breaking Changes section first (if any)
230
- - Grouped sections: `### Features`, `### Bug Fixes`, etc.
231
- - One bullet per commit with the commit message (not the hash)
232
- - A `**Full Changelog**: <last-tag>...<new-tag>` line at the end
233
- - Keep it concise and factual. Do not invent changes that are not in the log.
234
-
235
- 5. Call `noop` and stop. The deterministic `conclude` job reads the notes you wrote
236
- and handles version bumping, tagging, and release creation.
237
-
238
- ## Diagram
239
-
240
- ```mermaid
241
- flowchart TD
242
- relStart("Work Router<br/>release route<br/>(manual dispatch)") --> relActivation
243
- relActivation("Activation<br/>Prepare prompt + env") --> relPreAgent
244
- relPreAgent["Pre-agent<br/>Write git log + version to /tmp"] --> relAgent
245
- relAgent["Agent<br/>Read commit log<br/>Write release-notes.md"] --> relNoop
246
- relNoop("Safe Outputs<br/>Process noop") --> relConclude
247
- relConclude["Conclude<br/>Bump version, commit, tag<br/>push, create GitHub Release"]
248
- relConclude --> relDone(("Released<br/>Tag + GitHub Release created"))
249
- relConclude -.->|failure| relFail(("Failed<br/>No tag created"))
250
- classDef start fill:#ffffff,stroke:#172033,stroke-width:2px,color:#172033
251
- classDef action fill:#eef0ff,stroke:#554cff,stroke-width:2px,color:#172033
252
- classDef success fill:#e8f8ec,stroke:#18883c,stroke-width:2px,color:#145a32
253
- classDef failure fill:#fff0f0,stroke:#ef2929,stroke-width:2px,color:#8b1a2a
254
- class relStart start
255
- class relActivation,relPreAgent,relAgent action
256
- class relDone success
257
- class relFail failure
258
- ```
1
+ ---
2
+ # Managed by @plainconceptsplatform/workflows. Source: loops/workflows/agent-release.md. Update with `workflows update --force`; consumer edits may be overwritten.
3
+ env:
4
+ GIT_AUTHOR_NAME: "github-actions[bot]"
5
+ GIT_AUTHOR_EMAIL: "github-actions[bot]@users.noreply.github.com"
6
+ GIT_COMMITTER_NAME: "github-actions[bot]"
7
+ GIT_COMMITTER_EMAIL: "github-actions[bot]@users.noreply.github.com"
8
+ description: |
9
+ Generates release notes from the commit log and creates a tagged GitHub Release.
10
+ The agent writes human-readable release notes; every other step (version bump,
11
+ commit, tag, push, release creation) is deterministic.
12
+
13
+ Router-only worker: triggered exclusively via workflow_call from work-router.yml.
14
+ Contract input: version-bump(patch|minor|major|auto).
15
+
16
+ name: "Agent: Release"
17
+
18
+ imports:
19
+ - github/gh-aw/.github/workflows/shared/opencode.md@v0.87.5
20
+ - shared/platform-defaults.md
21
+ - shared/opencode-ci.md
22
+
23
+ on:
24
+ workflow_call:
25
+ inputs:
26
+ version-bump:
27
+ description: "Version bump strategy: patch, minor, major, or auto"
28
+ required: false
29
+ type: string
30
+ default: "auto"
31
+
32
+ runs-on: agents-arc
33
+ runs-on-slim: agents-arc
34
+
35
+ secrets:
36
+ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
37
+
38
+ engine:
39
+ id: opencode
40
+ version: "1.2.14"
41
+ env:
42
+ OPENAI_BASE_URL: https://forge.plainconcepts.com/v1
43
+
44
+ model: openai/glm-5-3
45
+
46
+ max-turns: 100
47
+ max-turn-cache-misses: 3000
48
+ max-ai-credits: 2000
49
+
50
+ permissions: read-all
51
+
52
+ checkout:
53
+ fetch: ["*"]
54
+ fetch-depth: 0
55
+
56
+ steps:
57
+ - name: Prepare release context
58
+ env:
59
+ GH_TOKEN: ${{ github.token }}
60
+ REPO: ${{ github.repository }}
61
+ run: |
62
+ set -euo pipefail
63
+ mkdir -p /tmp/gh-aw/agent
64
+
65
+ last_tag=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
66
+ if [ -n "$last_tag" ]; then
67
+ git log --oneline --no-decorate "${last_tag}..HEAD" > /tmp/gh-aw/agent/git-log.txt
68
+ else
69
+ git log --oneline --no-decorate -50 > /tmp/gh-aw/agent/git-log.txt
70
+ fi
71
+
72
+ version=$(node -p "require('./package.json').version" 2>/dev/null || echo "0.0.0")
73
+ echo "$version" > /tmp/gh-aw/agent/current-version.txt
74
+
75
+ echo "Last tag: ${last_tag:-none}"
76
+ echo "Current version: $version"
77
+
78
+ safe-outputs:
79
+ report-failure-as-issue: false
80
+ threat-detection: false
81
+ noop:
82
+ max: 1
83
+
84
+ # The fleet is two machines, so this clock is also how long a stuck run can hold half of it.
85
+ # 240 went on to every worker at once when the provider was slow, which fixed the deaths and
86
+ # made every worker equally expensive to hang. These numbers are per worker: enough headroom
87
+ # for a slow gateway on the work it actually does, and not four hours for a run that reads one
88
+ # issue. Turns remain the guard against a confused agent looping; for a custom model the credit
89
+ # ceiling is models.dev fallback pricing and guards nothing.
90
+ #
91
+ # Reads a commit log already on disk and writes release notes. Nothing else.
92
+ timeout-minutes: 30
93
+
94
+ jobs:
95
+ conclude:
96
+ needs: [activation, agent, safe_outputs]
97
+ if: >
98
+ always() &&
99
+ needs.agent.result == 'success' &&
100
+ needs.safe_outputs.result == 'success'
101
+ runs-on: agents-arc
102
+ permissions:
103
+ contents: write
104
+ steps:
105
+ - name: Download agent output artifact
106
+ id: download-agent-output
107
+ continue-on-error: true
108
+ uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
109
+ with:
110
+ pattern: "{${{ needs.activation.outputs.artifact_prefix }}agent,${{ needs.activation.outputs.artifact_prefix }}agent-output-fallback}"
111
+ merge-multiple: true
112
+ path: /tmp/gh-aw/
113
+ - name: Checkout repository
114
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
115
+ with:
116
+ token: ${{ github.token }}
117
+ fetch-depth: 0
118
+ - name: Read release notes and determine version
119
+ id: release
120
+ env:
121
+ VERSION_BUMP: ${{ inputs.version-bump }}
122
+ run: |
123
+ set -euo pipefail
124
+
125
+ notes="/tmp/gh-aw/agent/release-notes.md"
126
+ if [ ! -f "$notes" ]; then
127
+ echo "::error::Agent did not write release-notes.md"
128
+ exit 1
129
+ fi
130
+
131
+ current=$(node -p "require('./package.json').version" 2>/dev/null || echo "0.0.0")
132
+ echo "current_version=$current" >> "$GITHUB_OUTPUT"
133
+
134
+ # Determine the version bump
135
+ bump="$VERSION_BUMP"
136
+ if [ "$bump" = "auto" ]; then
137
+ if grep -qiE 'BREAKING CHANGE' "$notes" || grep -qE '\w+\(!:' /tmp/gh-aw/agent/git-log.txt; then
138
+ bump="major"
139
+ elif grep -qE '^feat(\(.+\))?:' /tmp/gh-aw/agent/git-log.txt; then
140
+ bump="minor"
141
+ else
142
+ bump="patch"
143
+ fi
144
+ fi
145
+
146
+ # Semver bump
147
+ IFS='.' read -r major minor patch <<< "$current"
148
+ case "$bump" in
149
+ major) major=$((major + 1)); minor=0; patch=0 ;;
150
+ minor) minor=$((minor + 1)); patch=0 ;;
151
+ patch) patch=$((patch + 1)) ;;
152
+ *) echo "::error::Unknown version-bump: $bump"; exit 1 ;;
153
+ esac
154
+ new_version="${major}.${minor}.${patch}"
155
+ echo "new_version=$new_version" >> "$GITHUB_OUTPUT"
156
+ echo "Determined version: $current -> $new_version (bump: $bump)"
157
+
158
+ # Copy notes to a clean location the release step can read
159
+ cp "$notes" /tmp/release-notes.md
160
+ - name: Bump version in package.json
161
+ env:
162
+ NEW_VERSION: ${{ steps.release.outputs.new_version }}
163
+ run: |
164
+ set -euo pipefail
165
+ node -e "
166
+ const fs = require('fs');
167
+ for (const file of ['package.json', 'cli/package.json']) {
168
+ if (fs.existsSync(file)) {
169
+ const pkg = JSON.parse(fs.readFileSync(file, 'utf8'));
170
+ pkg.version = process.env.NEW_VERSION;
171
+ fs.writeFileSync(file, JSON.stringify(pkg, null, 2) + '\n');
172
+ console.log('Bumped ' + file + ' to ' + process.env.NEW_VERSION);
173
+ }
174
+ }
175
+ "
176
+ - name: Commit, tag, and push
177
+ env:
178
+ NEW_VERSION: ${{ steps.release.outputs.new_version }}
179
+ GH_TOKEN: ${{ github.token }}
180
+ run: |
181
+ set -euo pipefail
182
+ git config user.name "github-actions[bot]"
183
+ git config user.email "github-actions[bot]@users.noreply.github.com"
184
+ git add package.json
185
+ [ -f cli/package.json ] && git add cli/package.json
186
+ git commit -m "chore(release): v${NEW_VERSION}"
187
+ git tag "v${NEW_VERSION}"
188
+ git push
189
+ git push --tags
190
+ echo "Tagged v${NEW_VERSION} and pushed."
191
+ - name: Create GitHub Release
192
+ env:
193
+ NEW_VERSION: ${{ steps.release.outputs.new_version }}
194
+ GH_TOKEN: ${{ github.token }}
195
+ run: |
196
+ set -euo pipefail
197
+ gh release create "v${NEW_VERSION}" \
198
+ --repo "$GITHUB_REPOSITORY" \
199
+ --title "v${NEW_VERSION}" \
200
+ --notes-file /tmp/release-notes.md
201
+ echo "GitHub Release v${NEW_VERSION} created."
202
+
203
+ incomplete:
204
+ needs: [agent, safe_outputs]
205
+ if: >
206
+ always() &&
207
+ (needs.agent.result != 'success' || needs.safe_outputs.result != 'success')
208
+ runs-on: agents-arc
209
+ permissions:
210
+ contents: read
211
+ steps:
212
+ - name: Report release failure
213
+ run: |
214
+ echo "::error::Release agent did not complete successfully."
215
+ echo "The release was not created. Check the agent logs."
216
+ exit 1
217
+
218
+ ---
219
+
220
+ 1. Read `/tmp/gh-aw/agent/git-log.txt`. It contains the commit log since the last
221
+ tag (or the last 50 commits if no tag exists).
222
+
223
+ 2. Read `/tmp/gh-aw/agent/current-version.txt` for the current version.
224
+
225
+ 3. Categorize commits by conventional-commit prefix:
226
+ - `feat:` / `feat(scope):` → Features
227
+ - `fix:` / `fix(scope):` → Bug Fixes
228
+ - `chore:` / `chore(scope):` → Maintenance
229
+ - `docs:` → Documentation
230
+ - `refactor:` → Refactoring
231
+ - `perf:` → Performance
232
+ - Any `BREAKING CHANGE` footer or `!:` prefix → Breaking Changes (top of the notes)
233
+
234
+ 4. Write structured release notes in markdown to `/tmp/gh-aw/agent/release-notes.md`.
235
+ Format:
236
+ - A `## What's Changed` heading
237
+ - Breaking Changes section first (if any)
238
+ - Grouped sections: `### Features`, `### Bug Fixes`, etc.
239
+ - One bullet per commit with the commit message (not the hash)
240
+ - A `**Full Changelog**: <last-tag>...<new-tag>` line at the end
241
+ - Keep it concise and factual. Do not invent changes that are not in the log.
242
+
243
+ 5. Call `noop` and stop. The deterministic `conclude` job reads the notes you wrote
244
+ and handles version bumping, tagging, and release creation.