@plainconceptsplatform/workflows 0.20.2 → 0.20.3
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/dist/index.js +0 -0
- package/dist/stack-defaults.js +16 -16
- package/dist/workflow-catalog.d.ts +1 -1
- package/dist/workflow-catalog.js +2 -0
- package/loops/actions/add-issue-labels/action.yml +50 -50
- package/loops/actions/agent-output.cjs +17 -17
- package/loops/actions/apply-agent-bundle/action.yml +24 -24
- package/loops/actions/apply-agent-comments/action.yml +42 -42
- package/loops/actions/apply-agent-labels/action.yml +55 -55
- package/loops/actions/apply-agent-output/action.yml +108 -108
- package/loops/actions/classify-route/action.yml +100 -100
- package/loops/actions/cleanup-artifacts/action.yml +91 -91
- package/loops/actions/close-agent-issues/action.yml +43 -43
- package/loops/actions/collect-app-errors/action.yml +297 -0
- package/loops/actions/collect-app-errors/group-and-redact.mjs +252 -0
- package/loops/actions/collect-app-errors/query-app-errors.sh +104 -0
- package/loops/actions/create-agent-issues/action.yml +52 -52
- package/loops/actions/create-issue-comment/action.yml +29 -29
- package/loops/actions/download-agent-output/action.yml +53 -53
- package/loops/actions/link-pr-to-issue/action.yml +40 -40
- package/loops/actions/list-open-issues/action.yml +33 -33
- package/loops/actions/load-issue-context/action.yml +45 -45
- package/loops/actions/merge-agent-pr/action.yml +49 -49
- package/loops/actions/push-agent-branch/action.yml +45 -45
- package/loops/actions/remove-issue-labels/action.yml +37 -37
- package/loops/actions/update-agent-issues/action.yml +58 -58
- package/loops/actions/validate-review-output/action.yml +35 -35
- package/loops/actions/validate-triage-output/action.yml +36 -36
- package/loops/actions/verify-app-errors/action.yml +11 -0
- package/loops/actions/verify-app-errors/verify-app-errors.mjs +216 -0
- package/loops/actions/verify-composite-actions/action.yml +9 -9
- package/loops/actions/verify-refine-output/action.yml +9 -9
- package/loops/actions/verify-route-matrix/action.yml +9 -9
- package/loops/actions/verify-route-matrix/verify-route-matrix.sh +88 -0
- package/loops/scripts/compile-agent-workflows.mjs +331 -331
- package/loops/templates/agentics/agentics-app-errors.yml +168 -0
- package/loops/templates/agentics/agentics-maintenance.yml +121 -121
- package/loops/templates/ci/app-ci-dotnet-next.yml +330 -330
- package/loops/templates/ci/app-ci-node-monorepo.yml +260 -260
- package/loops/templates/issues/bug_report.yml +109 -109
- package/loops/templates/issues/feature_request.yml +75 -75
- package/loops/templates/release/github-release.yml +30 -30
- package/loops/workflows/authorize-bot-work.yml +105 -105
- package/loops/workflows/shared/opencode-ci.md +206 -206
- package/loops/workflows/shared/platform-defaults.md +19 -19
- package/package.json +9 -8
|
@@ -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: [self-hosted, linux, agents]
|
|
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: [self-hosted, linux, agents]
|
|
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,105 +1,105 @@
|
|
|
1
|
-
# Managed by @plainconceptsplatform/workflows. Source: loops/workflows/authorize-bot-work.yml. Update with `workflows update --force`; consumer edits may be overwritten.
|
|
2
|
-
# Human adds implement/refine/direct/feature label → validates permission → bot adds bot-working
|
|
3
|
-
# This ensures the bot is the actor for all agentic workflows.
|
|
4
|
-
#
|
|
5
|
-
# IMPORTANT: Only triggers for HUMAN actors. When the bot transitions refine→implement,
|
|
6
|
-
# it adds bot-working itself, so authorize-bot-work must not fire again.
|
|
7
|
-
name: "Authorize Bot Work"
|
|
8
|
-
|
|
9
|
-
run-name: "Authorizing: ${{ github.event.issue.title }} (#${{ github.event.issue.number }})"
|
|
10
|
-
|
|
11
|
-
on:
|
|
12
|
-
issues:
|
|
13
|
-
types: [labeled]
|
|
14
|
-
|
|
15
|
-
permissions:
|
|
16
|
-
contents: read
|
|
17
|
-
|
|
18
|
-
jobs:
|
|
19
|
-
authorize:
|
|
20
|
-
# Only trigger for work labels from HUMANS (not bots), and only if another bot run does not
|
|
21
|
-
# already own the issue.
|
|
22
|
-
#
|
|
23
|
-
# `review` is deliberately NOT excluded. It used to be, and that made the label a one-way
|
|
24
|
-
# door: the classifier refuses to route while `review` is set, so a person adding `refine`
|
|
25
|
-
# to a parked issue got no run, no comment and no error anywhere. Triage's own
|
|
26
|
-
# needs-maintainer verdict tells the maintainer to add `refine`, which could not work.
|
|
27
|
-
#
|
|
28
|
-
# A person adding a work label IS the human review the label was waiting for, so this
|
|
29
|
-
# workflow clears it below before handing the issue to the bot. The classifier's own guard
|
|
30
|
-
# stays as it is: it exists to stop the *bot* re-triggering itself, and by the time
|
|
31
|
-
# bot-working is added `review` is already gone.
|
|
32
|
-
if: >
|
|
33
|
-
(github.event.label.name == 'implement' ||
|
|
34
|
-
github.event.label.name == 'refine') &&
|
|
35
|
-
!contains(github.event.issue.labels.*.name, 'bot-working') &&
|
|
36
|
-
!endsWith(github.actor, '[bot]')
|
|
37
|
-
runs-on: ubuntu-latest
|
|
38
|
-
timeout-minutes: 5
|
|
39
|
-
concurrency:
|
|
40
|
-
group: authorize-${{ github.event.issue.number }}
|
|
41
|
-
cancel-in-progress: false
|
|
42
|
-
permissions:
|
|
43
|
-
contents: read
|
|
44
|
-
issues: write
|
|
45
|
-
steps:
|
|
46
|
-
- name: Check actor permission
|
|
47
|
-
id: check
|
|
48
|
-
env:
|
|
49
|
-
GH_TOKEN: ${{ github.token }}
|
|
50
|
-
ACTOR: ${{ github.actor }}
|
|
51
|
-
run: |
|
|
52
|
-
set -euo pipefail
|
|
53
|
-
|
|
54
|
-
permission=$(gh api "repos/$GITHUB_REPOSITORY/collaborators/$ACTOR/permission" \
|
|
55
|
-
--jq '.permission' 2>/dev/null || echo "none")
|
|
56
|
-
|
|
57
|
-
case "$permission" in
|
|
58
|
-
admin | maintain | write)
|
|
59
|
-
echo "authorized=true" >> "$GITHUB_OUTPUT"
|
|
60
|
-
echo "::notice::$ACTOR has $permission permission - authorized"
|
|
61
|
-
;;
|
|
62
|
-
*)
|
|
63
|
-
echo "authorized=false" >> "$GITHUB_OUTPUT"
|
|
64
|
-
echo "::warning::$ACTOR has '$permission' permission - not authorized"
|
|
65
|
-
;;
|
|
66
|
-
esac
|
|
67
|
-
|
|
68
|
-
- name: Checkout for App token action
|
|
69
|
-
if: steps.check.outputs.authorized == 'true'
|
|
70
|
-
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
71
|
-
with:
|
|
72
|
-
persist-credentials: false
|
|
73
|
-
|
|
74
|
-
- name: Generate App token
|
|
75
|
-
if: steps.check.outputs.authorized == 'true'
|
|
76
|
-
id: app-token
|
|
77
|
-
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
|
78
|
-
with:
|
|
79
|
-
app-id: ${{ secrets.BOT_APP_ID }}
|
|
80
|
-
private-key: ${{ secrets.BOT_PRIVATE_KEY }}
|
|
81
|
-
|
|
82
|
-
- name: Bot takes the issue over
|
|
83
|
-
if: steps.check.outputs.authorized == 'true'
|
|
84
|
-
env:
|
|
85
|
-
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
86
|
-
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
|
87
|
-
LABEL: ${{ github.event.label.name }}
|
|
88
|
-
run: |
|
|
89
|
-
set -euo pipefail
|
|
90
|
-
|
|
91
|
-
# Clear review FIRST. A person adding a work label is the human review the label was
|
|
92
|
-
# waiting for, and the classifier refuses to route an issue that still carries it, so
|
|
93
|
-
# removing it here is what makes the hand-off work at all. It also has to happen
|
|
94
|
-
# before bot-working, because that is the event the classifier reads: adding
|
|
95
|
-
# bot-working first would raise an event whose payload still shows review.
|
|
96
|
-
# --remove-label on an absent label is a no-op, so this is safe on a fresh issue.
|
|
97
|
-
# `stalled` goes with it: a person taking the issue on restarts the work, so the
|
|
98
|
-
# marker the janitor retries on must not survive into the new run.
|
|
99
|
-
gh issue edit "$ISSUE_NUMBER" --remove-label "review" --remove-label "stalled" 2>/dev/null ||
|
|
100
|
-
echo "::notice::no review or stalled label to clear on #$ISSUE_NUMBER"
|
|
101
|
-
|
|
102
|
-
echo "Adding bot-working label to issue #$ISSUE_NUMBER (triggered by $LABEL)"
|
|
103
|
-
gh issue edit "$ISSUE_NUMBER" --add-label "bot-working"
|
|
104
|
-
|
|
105
|
-
echo "::notice::bot-working label added - bot will now own the $LABEL workflow"
|
|
1
|
+
# Managed by @plainconceptsplatform/workflows. Source: loops/workflows/authorize-bot-work.yml. Update with `workflows update --force`; consumer edits may be overwritten.
|
|
2
|
+
# Human adds implement/refine/direct/feature label → validates permission → bot adds bot-working
|
|
3
|
+
# This ensures the bot is the actor for all agentic workflows.
|
|
4
|
+
#
|
|
5
|
+
# IMPORTANT: Only triggers for HUMAN actors. When the bot transitions refine→implement,
|
|
6
|
+
# it adds bot-working itself, so authorize-bot-work must not fire again.
|
|
7
|
+
name: "Authorize Bot Work"
|
|
8
|
+
|
|
9
|
+
run-name: "Authorizing: ${{ github.event.issue.title }} (#${{ github.event.issue.number }})"
|
|
10
|
+
|
|
11
|
+
on:
|
|
12
|
+
issues:
|
|
13
|
+
types: [labeled]
|
|
14
|
+
|
|
15
|
+
permissions:
|
|
16
|
+
contents: read
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
authorize:
|
|
20
|
+
# Only trigger for work labels from HUMANS (not bots), and only if another bot run does not
|
|
21
|
+
# already own the issue.
|
|
22
|
+
#
|
|
23
|
+
# `review` is deliberately NOT excluded. It used to be, and that made the label a one-way
|
|
24
|
+
# door: the classifier refuses to route while `review` is set, so a person adding `refine`
|
|
25
|
+
# to a parked issue got no run, no comment and no error anywhere. Triage's own
|
|
26
|
+
# needs-maintainer verdict tells the maintainer to add `refine`, which could not work.
|
|
27
|
+
#
|
|
28
|
+
# A person adding a work label IS the human review the label was waiting for, so this
|
|
29
|
+
# workflow clears it below before handing the issue to the bot. The classifier's own guard
|
|
30
|
+
# stays as it is: it exists to stop the *bot* re-triggering itself, and by the time
|
|
31
|
+
# bot-working is added `review` is already gone.
|
|
32
|
+
if: >
|
|
33
|
+
(github.event.label.name == 'implement' ||
|
|
34
|
+
github.event.label.name == 'refine') &&
|
|
35
|
+
!contains(github.event.issue.labels.*.name, 'bot-working') &&
|
|
36
|
+
!endsWith(github.actor, '[bot]')
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
timeout-minutes: 5
|
|
39
|
+
concurrency:
|
|
40
|
+
group: authorize-${{ github.event.issue.number }}
|
|
41
|
+
cancel-in-progress: false
|
|
42
|
+
permissions:
|
|
43
|
+
contents: read
|
|
44
|
+
issues: write
|
|
45
|
+
steps:
|
|
46
|
+
- name: Check actor permission
|
|
47
|
+
id: check
|
|
48
|
+
env:
|
|
49
|
+
GH_TOKEN: ${{ github.token }}
|
|
50
|
+
ACTOR: ${{ github.actor }}
|
|
51
|
+
run: |
|
|
52
|
+
set -euo pipefail
|
|
53
|
+
|
|
54
|
+
permission=$(gh api "repos/$GITHUB_REPOSITORY/collaborators/$ACTOR/permission" \
|
|
55
|
+
--jq '.permission' 2>/dev/null || echo "none")
|
|
56
|
+
|
|
57
|
+
case "$permission" in
|
|
58
|
+
admin | maintain | write)
|
|
59
|
+
echo "authorized=true" >> "$GITHUB_OUTPUT"
|
|
60
|
+
echo "::notice::$ACTOR has $permission permission - authorized"
|
|
61
|
+
;;
|
|
62
|
+
*)
|
|
63
|
+
echo "authorized=false" >> "$GITHUB_OUTPUT"
|
|
64
|
+
echo "::warning::$ACTOR has '$permission' permission - not authorized"
|
|
65
|
+
;;
|
|
66
|
+
esac
|
|
67
|
+
|
|
68
|
+
- name: Checkout for App token action
|
|
69
|
+
if: steps.check.outputs.authorized == 'true'
|
|
70
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
71
|
+
with:
|
|
72
|
+
persist-credentials: false
|
|
73
|
+
|
|
74
|
+
- name: Generate App token
|
|
75
|
+
if: steps.check.outputs.authorized == 'true'
|
|
76
|
+
id: app-token
|
|
77
|
+
uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
|
|
78
|
+
with:
|
|
79
|
+
app-id: ${{ secrets.BOT_APP_ID }}
|
|
80
|
+
private-key: ${{ secrets.BOT_PRIVATE_KEY }}
|
|
81
|
+
|
|
82
|
+
- name: Bot takes the issue over
|
|
83
|
+
if: steps.check.outputs.authorized == 'true'
|
|
84
|
+
env:
|
|
85
|
+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
|
86
|
+
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
|
87
|
+
LABEL: ${{ github.event.label.name }}
|
|
88
|
+
run: |
|
|
89
|
+
set -euo pipefail
|
|
90
|
+
|
|
91
|
+
# Clear review FIRST. A person adding a work label is the human review the label was
|
|
92
|
+
# waiting for, and the classifier refuses to route an issue that still carries it, so
|
|
93
|
+
# removing it here is what makes the hand-off work at all. It also has to happen
|
|
94
|
+
# before bot-working, because that is the event the classifier reads: adding
|
|
95
|
+
# bot-working first would raise an event whose payload still shows review.
|
|
96
|
+
# --remove-label on an absent label is a no-op, so this is safe on a fresh issue.
|
|
97
|
+
# `stalled` goes with it: a person taking the issue on restarts the work, so the
|
|
98
|
+
# marker the janitor retries on must not survive into the new run.
|
|
99
|
+
gh issue edit "$ISSUE_NUMBER" --remove-label "review" --remove-label "stalled" 2>/dev/null ||
|
|
100
|
+
echo "::notice::no review or stalled label to clear on #$ISSUE_NUMBER"
|
|
101
|
+
|
|
102
|
+
echo "Adding bot-working label to issue #$ISSUE_NUMBER (triggered by $LABEL)"
|
|
103
|
+
gh issue edit "$ISSUE_NUMBER" --add-label "bot-working"
|
|
104
|
+
|
|
105
|
+
echo "::notice::bot-working label added - bot will now own the $LABEL workflow"
|