create-agentic-pdlc 2.0.0 โ 2.0.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/.github/CODEOWNERS +5 -0
- package/.github/copilot-instructions.md +12 -0
- package/.github/workflows/agent-trigger.yml +6 -4
- package/.github/workflows/auto-approve.yml +16 -0
- package/.github/workflows/ci.yml +12 -4
- package/.github/workflows/npm-publish.yml +1 -1
- package/.github/workflows/project-automation.yml +40 -12
- package/.github/workflows/protect-workflows.yml +21 -0
- package/.github/workflows/qa-agent.yml +27 -0
- package/AGENTS.md +8 -7
- package/SETUP.md +15 -28
- package/adapters/claude-code/skill.md +3 -2
- package/bin/cli.js +4 -2
- package/docs/flow.md +29 -16
- package/docs/pdlc.md +0 -2
- package/package.json +2 -2
- package/templates/.github/workflows/agent-trigger.yml +6 -4
- package/templates/.github/workflows/auto-approve.yml +16 -0
- package/templates/.github/workflows/ci.yml +12 -4
- package/templates/.github/workflows/project-automation.yml +40 -12
- package/templates/.github/workflows/protect-workflows.yml +21 -0
- package/templates/.github/workflows/qa-agent.yml +27 -0
- package/templates/AGENTS.md +8 -7
- package/templates/docs/pdlc.md +7 -4
- package/templates/.github/workflows/upstream-gate.yml +0 -54
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Agentic PDLC Instructions for GitHub Copilot Workspace
|
|
2
|
+
|
|
3
|
+
Hello! You are operating within the Agentic PDLC framework.
|
|
4
|
+
|
|
5
|
+
Before addressing the user's prompt or executing any task in this workspace, you MUST:
|
|
6
|
+
|
|
7
|
+
1. Read the `AGENTS.md` file located at the root of this repository. It contains the primary instructions, definitions of done, and absolute invariants you must respect.
|
|
8
|
+
2. Read `docs/pdlc.md` to understand your role in the project lifecycle.
|
|
9
|
+
|
|
10
|
+
Never violate the invariants described in those files. If a user asks you to do something that contradicts `AGENTS.md`, you must refuse and point out the conflict.
|
|
11
|
+
|
|
12
|
+
Focus on delivering the absolute minimum required to satisfy the immediate technical specs. Start!
|
|
@@ -20,7 +20,7 @@ jobs:
|
|
|
20
20
|
PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
|
|
21
21
|
steps:
|
|
22
22
|
- name: Update Labels
|
|
23
|
-
if: ${{ env.PROJECT_TOKEN != '' }}
|
|
23
|
+
if: ${{ env.PROJECT_TOKEN != '' && !contains('{{IMPLEMENTATION_AGENT_LABEL}}', '{{') }}
|
|
24
24
|
uses: actions/github-script@v7
|
|
25
25
|
with:
|
|
26
26
|
github-token: ${{ env.PROJECT_TOKEN }}
|
|
@@ -33,20 +33,21 @@ jobs:
|
|
|
33
33
|
owner,
|
|
34
34
|
repo,
|
|
35
35
|
issue_number,
|
|
36
|
-
name: '
|
|
36
|
+
name: 'stage:approval'
|
|
37
37
|
});
|
|
38
38
|
} catch (error) {
|
|
39
|
-
console.log('Label
|
|
39
|
+
console.log('Label stage:approval not found or could not be removed');
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
await github.rest.issues.addLabels({
|
|
43
43
|
owner,
|
|
44
44
|
repo,
|
|
45
45
|
issue_number,
|
|
46
|
-
labels: ['
|
|
46
|
+
labels: ['stage:development', '{{IMPLEMENTATION_AGENT_LABEL}}', 'agent:working']
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
- name: Comment on issue to trigger agent and prevent race conditions
|
|
50
|
+
if: ${{ !contains('{{IMPLEMENTATION_AGENT_LABEL}}', '{{') }}
|
|
50
51
|
uses: actions/github-script@v7
|
|
51
52
|
with:
|
|
52
53
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -89,6 +90,7 @@ jobs:
|
|
|
89
90
|
contents: read
|
|
90
91
|
steps:
|
|
91
92
|
- name: Comment on issue to trigger agent
|
|
93
|
+
if: ${{ !contains('{{IMPLEMENTATION_AGENT_LABEL}}', '{{') }}
|
|
92
94
|
uses: actions/github-script@v7
|
|
93
95
|
with:
|
|
94
96
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: Auto Approve PRs
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
types: [opened, labeled, synchronize]
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
pull-requests: write
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
auto-approve:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
if: contains(github.event.pull_request.labels.*.name, 'auto-approve')
|
|
13
|
+
steps:
|
|
14
|
+
- uses: hmarr/auto-approve-action@v4
|
|
15
|
+
with:
|
|
16
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
package/.github/workflows/ci.yml
CHANGED
|
@@ -20,13 +20,21 @@ jobs:
|
|
|
20
20
|
run: echo "Replace this with your package manager install command"
|
|
21
21
|
|
|
22
22
|
- name: Run Linters
|
|
23
|
-
|
|
23
|
+
if: ${{ !contains('{{LINT_COMMAND}}', '{{') }}
|
|
24
|
+
run: |
|
|
25
|
+
{{LINT_COMMAND}}
|
|
24
26
|
|
|
25
27
|
- name: Typecheck
|
|
26
|
-
|
|
28
|
+
if: ${{ !contains('{{TYPECHECK_COMMAND}}', '{{') }}
|
|
29
|
+
run: |
|
|
30
|
+
{{TYPECHECK_COMMAND}}
|
|
27
31
|
|
|
28
32
|
- name: Build
|
|
29
|
-
|
|
33
|
+
if: ${{ !contains('{{BUILD_COMMAND}}', '{{') }}
|
|
34
|
+
run: |
|
|
35
|
+
{{BUILD_COMMAND}}
|
|
30
36
|
|
|
31
37
|
- name: Run Tests
|
|
32
|
-
|
|
38
|
+
if: ${{ !contains('{{TEST_COMMAND}}', '{{') }}
|
|
39
|
+
run: |
|
|
40
|
+
{{TEST_COMMAND}}
|
|
@@ -27,7 +27,7 @@ jobs:
|
|
|
27
27
|
# Strip 'v' from tag (e.g., v1.0.2 -> 1.0.2)
|
|
28
28
|
VERSION=${GITHUB_REF_NAME#v}
|
|
29
29
|
echo "Setting package version to $VERSION"
|
|
30
|
-
npm version $VERSION --no-git-tag-version
|
|
30
|
+
npm version $VERSION --no-git-tag-version --allow-same-version
|
|
31
31
|
|
|
32
32
|
- name: Install Dependencies
|
|
33
33
|
run: npm install
|
|
@@ -11,6 +11,7 @@ on:
|
|
|
11
11
|
env:
|
|
12
12
|
PROJECT_ID: "{{PROJECT_ID}}"
|
|
13
13
|
STATUS_FIELD_ID: "{{STATUS_FIELD_ID}}"
|
|
14
|
+
STATUS_IDEA: "{{ID_IDEA}}"
|
|
14
15
|
STATUS_EXPLORATION: "{{ID_EXPLORATION}}"
|
|
15
16
|
STATUS_BRAINSTORMING: "{{ID_BRAINSTORMING}}"
|
|
16
17
|
STATUS_DETAILING: "{{ID_DETAILING}}"
|
|
@@ -30,7 +31,7 @@ jobs:
|
|
|
30
31
|
PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
|
|
31
32
|
steps:
|
|
32
33
|
- name: Detect Label and Move Issue
|
|
33
|
-
if: ${{ env.PROJECT_TOKEN != '' }}
|
|
34
|
+
if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
|
|
34
35
|
uses: actions/github-script@v7
|
|
35
36
|
with:
|
|
36
37
|
github-token: ${{ env.PROJECT_TOKEN }}
|
|
@@ -39,28 +40,28 @@ jobs:
|
|
|
39
40
|
let targetStatusId = null;
|
|
40
41
|
let stageName = null;
|
|
41
42
|
|
|
42
|
-
if (labelName === '
|
|
43
|
+
if (labelName === 'stage:exploration') {
|
|
43
44
|
targetStatusId = process.env.STATUS_EXPLORATION;
|
|
44
45
|
stageName = 'Exploration';
|
|
45
|
-
} else if (labelName === '
|
|
46
|
+
} else if (labelName === 'stage:brainstorming') {
|
|
46
47
|
targetStatusId = process.env.STATUS_BRAINSTORMING;
|
|
47
48
|
stageName = 'Brainstorming';
|
|
48
|
-
} else if (labelName === '
|
|
49
|
+
} else if (labelName === 'stage:detailing') {
|
|
49
50
|
targetStatusId = process.env.STATUS_DETAILING;
|
|
50
51
|
stageName = 'Detailing';
|
|
51
|
-
} else if (labelName === '
|
|
52
|
+
} else if (labelName === 'stage:approval') {
|
|
52
53
|
targetStatusId = process.env.STATUS_APPROVAL;
|
|
53
54
|
stageName = 'Approval';
|
|
54
|
-
} else if (labelName === '
|
|
55
|
+
} else if (labelName === 'stage:development') {
|
|
55
56
|
targetStatusId = process.env.STATUS_DEVELOPMENT;
|
|
56
57
|
stageName = 'Development';
|
|
57
|
-
} else if (labelName === '
|
|
58
|
+
} else if (labelName === 'stage:testing') {
|
|
58
59
|
targetStatusId = process.env.STATUS_TESTING;
|
|
59
60
|
stageName = 'Testing';
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
if (!targetStatusId) {
|
|
63
|
-
console.log('No
|
|
64
|
+
console.log('No stage PDLC label found. Skipping.');
|
|
64
65
|
return;
|
|
65
66
|
}
|
|
66
67
|
|
|
@@ -86,9 +87,36 @@ jobs:
|
|
|
86
87
|
await moveItem(node_id, targetStatusId);
|
|
87
88
|
console.log(`Issue #${number} moved to ${stageName}`);
|
|
88
89
|
|
|
89
|
-
|
|
90
|
+
# OPTIONAL: Uncomment to enable architecture-violation โ Idea
|
|
91
|
+
# move-violation-to-board:
|
|
92
|
+
# name: architecture-violation โ ๐ก Idea
|
|
93
|
+
# if: github.event_name == 'issues' && github.event.action == 'labeled' && github.event.label.name == 'architecture-violation'
|
|
94
|
+
# runs-on: ubuntu-latest
|
|
95
|
+
# steps:
|
|
96
|
+
# - name: Move issue to Idea
|
|
97
|
+
# if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
|
|
98
|
+
# uses: actions/github-script@v7
|
|
99
|
+
# with:
|
|
100
|
+
# github-token: ${{ env.PROJECT_TOKEN }}
|
|
101
|
+
# script: |
|
|
102
|
+
# const { issue: { number, node_id } } = context.payload;
|
|
103
|
+
# const { addProjectV2ItemById: { item } } = await github.graphql(`
|
|
104
|
+
# mutation($p: ID!, $c: ID!) {
|
|
105
|
+
# addProjectV2ItemById(input: {projectId: $p, contentId: $c}) { item { id } }
|
|
106
|
+
# }`, { p: process.env.PROJECT_ID, c: node_id });
|
|
107
|
+
# await github.graphql(`
|
|
108
|
+
# mutation($p: ID!, $i: ID!, $f: ID!, $v: ProjectV2FieldValue!) {
|
|
109
|
+
# updateProjectV2ItemFieldValue(input: {projectId: $p, itemId: $i, fieldId: $f, value: $v}) {
|
|
110
|
+
# projectV2Item { id }
|
|
111
|
+
# }
|
|
112
|
+
# }`, {
|
|
113
|
+
# p: process.env.PROJECT_ID, i: item.id, f: process.env.STATUS_FIELD_ID,
|
|
114
|
+
# v: { singleSelectOptionId: process.env.STATUS_IDEA }
|
|
115
|
+
# });
|
|
116
|
+
# console.log(`Issue #${number} moved to Idea`);
|
|
90
117
|
|
|
91
118
|
# PR Opened โ Move linked issue to Code Review / PR
|
|
119
|
+
# ๐ก VARIANT B (QA Agent): If using an AI QA agent, change `STATUS_CODE_REVIEW_PR` to `STATUS_TESTING` on line ~158
|
|
92
120
|
move-card-on-pr-open:
|
|
93
121
|
name: Open PR โ Code Review / PR
|
|
94
122
|
if: github.event_name == 'pull_request' && (github.event.action == 'opened' || github.event.action == 'reopened')
|
|
@@ -97,7 +125,7 @@ jobs:
|
|
|
97
125
|
PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
|
|
98
126
|
steps:
|
|
99
127
|
- name: Move linked issue to Code Review / PR
|
|
100
|
-
if: ${{ env.PROJECT_TOKEN != '' }}
|
|
128
|
+
if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
|
|
101
129
|
uses: actions/github-script@v7
|
|
102
130
|
with:
|
|
103
131
|
github-token: ${{ env.PROJECT_TOKEN }}
|
|
@@ -151,7 +179,7 @@ jobs:
|
|
|
151
179
|
PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
|
|
152
180
|
steps:
|
|
153
181
|
- name: Swap PR labels
|
|
154
|
-
if: ${{ env.PROJECT_TOKEN != '' }}
|
|
182
|
+
if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
|
|
155
183
|
uses: actions/github-script@v7
|
|
156
184
|
with:
|
|
157
185
|
github-token: ${{ env.PROJECT_TOKEN }}
|
|
@@ -170,7 +198,7 @@ jobs:
|
|
|
170
198
|
PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
|
|
171
199
|
steps:
|
|
172
200
|
- name: Move issue to Production
|
|
173
|
-
if: ${{ env.PROJECT_TOKEN != '' }}
|
|
201
|
+
if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
|
|
174
202
|
uses: actions/github-script@v7
|
|
175
203
|
with:
|
|
176
204
|
github-token: ${{ env.PROJECT_TOKEN }}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: Protect Workflows
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize, reopened, labeled]
|
|
6
|
+
paths:
|
|
7
|
+
- '.github/**'
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
block-unauthorized-edits:
|
|
11
|
+
name: Protect .github directory
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- name: Check for Human Approval
|
|
15
|
+
if: ${{ !contains(github.event.pull_request.labels.*.name, 'human-approved') }}
|
|
16
|
+
run: |
|
|
17
|
+
echo "๐จ Modifications in the .github/ directory detected."
|
|
18
|
+
echo "As a security measure, this repository blocks workflow edits by default."
|
|
19
|
+
echo "If you are an AI Agent, do not add the approval label yourself."
|
|
20
|
+
echo "If you are the human owner, please add the 'human-approved' label to this PR to allow merging."
|
|
21
|
+
exit 1
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: AI QA Agent
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
types: [opened, synchronize, reopened]
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
pull-requests: write
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
qa:
|
|
12
|
+
name: Run AI QA Agent
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- name: Execute QA Tests
|
|
17
|
+
run: |
|
|
18
|
+
echo "Run your QA Agent here."
|
|
19
|
+
echo "This could be QAWolf, a custom LLM script, or a secondary agent."
|
|
20
|
+
echo "If tests pass: gh pr edit $PR_URL --add-label 'qa:pass'"
|
|
21
|
+
echo "If tests fail: gh pr edit $PR_URL --add-label 'qa:fail'"
|
|
22
|
+
|
|
23
|
+
# Example success:
|
|
24
|
+
# gh pr edit ${{ github.event.pull_request.html_url }} --add-label "qa:pass"
|
|
25
|
+
env:
|
|
26
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
27
|
+
PR_URL: ${{ github.event.pull_request.html_url }}
|
package/AGENTS.md
CHANGED
|
@@ -27,13 +27,14 @@ Always start from the current `main` HEAD. Never work over stale snapshots.
|
|
|
27
27
|
## Mandatory Workflow
|
|
28
28
|
|
|
29
29
|
0. **Identity**: Always prefix your GitHub comments with `๐ค **Agent:** ` to distinguish yourself.
|
|
30
|
-
1.
|
|
31
|
-
2. Read
|
|
32
|
-
3. Read
|
|
33
|
-
4.
|
|
34
|
-
5.
|
|
35
|
-
6. Run
|
|
36
|
-
7.
|
|
30
|
+
1. **Initial State**: When beginning work on a new issue, your very first action must be to apply the `stage:exploration` label using the GitHub CLI (`gh issue edit <N> --add-label "stage:exploration"`).
|
|
31
|
+
2. Read the issue entirely โ understand its type (US/BUG/TASK/SPIKE) and the Acceptance Criteria.
|
|
32
|
+
3. Read `docs/pdlc.md` โ understand the PDLC and the Definition of Done in this project.
|
|
33
|
+
4. Read all files mentioned in the issue's technical context.
|
|
34
|
+
5. Implement the **minimum viable change** that satisfies the ACs โ do not refactor beyond scope.
|
|
35
|
+
6. Run tests: `echo "No tests/build needed."`
|
|
36
|
+
7. Run typecheck: `echo "No typecheck needed."`
|
|
37
|
+
8. Create a Pull Request with `Closes #N` in the body โ automation moves the board.
|
|
37
38
|
|
|
38
39
|
## What NOT to do
|
|
39
40
|
|
package/SETUP.md
CHANGED
|
@@ -137,34 +137,21 @@ Move the issues to the `Idea` column on the board matching your setup.
|
|
|
137
137
|
|
|
138
138
|
## (Optional) Architecture Violation Integration
|
|
139
139
|
|
|
140
|
-
If your project uses an automated architecture auditing tool (e.g., a CI job that creates issues with an `architecture-violation` label),
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const addResult = await github.graphql(`
|
|
156
|
-
mutation($p: ID!, $c: ID!) {
|
|
157
|
-
addProjectV2ItemById(input: {projectId: $p, contentId: $c}) { item { id } }
|
|
158
|
-
}`, { p: process.env.PROJECT_ID, c: issueNodeId });
|
|
159
|
-
const itemId = addResult.addProjectV2ItemById.item.id;
|
|
160
|
-
await github.graphql(`
|
|
161
|
-
mutation($p: ID!, $i: ID!, $f: ID!, $v: ProjectV2FieldValue!) {
|
|
162
|
-
updateProjectV2ItemFieldValue(input: {projectId: $p, itemId: $i, fieldId: $f, value: $v}) {
|
|
163
|
-
projectV2Item { id }
|
|
164
|
-
}
|
|
165
|
-
}`, { p: process.env.PROJECT_ID, i: itemId, f: process.env.STATUS_FIELD_ID,
|
|
166
|
-
v: { singleSelectOptionId: process.env.STATUS_IDEA } });
|
|
167
|
-
```
|
|
140
|
+
If your project uses an automated architecture auditing tool (e.g., a CI job that creates issues with an `architecture-violation` label), you can easily integrate it with your project board.
|
|
141
|
+
|
|
142
|
+
Simply open `.github/workflows/project-automation.yml` and uncomment the `move-violation-to-board` job in the `jobs` section. This will automatically move any issues labeled with `architecture-violation` to the `Idea` column on your board.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## (Optional) AI QA Agent Integration (Variant B)
|
|
147
|
+
|
|
148
|
+
If you use an AI QA Agent (e.g., QAWolf, a secondary AI script) to test your PRs before Code Review, you can switch to **Variant B**.
|
|
149
|
+
|
|
150
|
+
Simply open `.github/workflows/project-automation.yml`:
|
|
151
|
+
1. In the `move-card-on-pr-open` job, change the PR destination from `STATUS_CODE_REVIEW_PR` to `STATUS_TESTING`.
|
|
152
|
+
2. Uncomment the `move-card-on-qa-pass` job at the bottom of the file to move tested issues to `Code Review / PR` upon receiving a `qa:pass` label.
|
|
153
|
+
|
|
154
|
+
If you don't use this, you can safely delete `templates/.github/workflows/qa-agent.yml`.
|
|
168
155
|
|
|
169
156
|
---
|
|
170
157
|
|
|
@@ -24,8 +24,9 @@ If any of these files are missing, you are in **Setup Mode**. Do not proceed wit
|
|
|
24
24
|
- **Project basics:** Project Name, Description, Technical Stack (Structure), and GitHub Username (for CODEOWNERS security).
|
|
25
25
|
- **Commands:** Test command, Lint command, Build command.
|
|
26
26
|
- **Invariants:** Critical business rules agents must never violate (e.g. Human-in-the-loop).
|
|
27
|
-
- **Board IDs:** PROJECT_ID, STATUS_FIELD_ID, column option IDs (provide standard PDLC options: Idea, Exploration, Brainstorming, Detail Solution, Approval, Development, Testing, Code Review / PR,
|
|
28
|
-
- **Architecture Violation:** Ask "Does your project use an automated architecture auditing tool (e.g., a CI job that creates issues with an `architecture-violation` label)?". If yes,
|
|
27
|
+
- **Board IDs:** PROJECT_ID, STATUS_FIELD_ID, column option IDs (provide standard PDLC options: Idea, Exploration, Brainstorming, Detail Solution, Approval, Development, Testing, Code Review / PR, Production). Allow user to answer "skip", which means you leave the placeholders intact.
|
|
28
|
+
- **Architecture Violation:** Ask "Does your project use an automated architecture auditing tool (e.g., a CI job that creates issues with an `architecture-violation` label)?". If yes, uncomment the `move-violation-to-board` job inside `project-automation.yml`. If no, ask if they would like help implementing one, reminding them that it significantly improves their agentic development process. If they decline, you can leave the job commented out.
|
|
29
|
+
- **QA Agent (Variant B):** Ask "Do you plan to use an AI QA Agent (e.g. QAWolf or a secondary script) to verify your PRs before Code Review?". If yes, explain you will adopt Variant B: you will change `STATUS_CODE_REVIEW_PR` to `STATUS_TESTING` inside the `move-card-on-pr-open` job in `project-automation.yml` and uncomment the `move-card-on-qa-pass` job. If no, leave the workflow as Variant A (default) and delete the optional `.github/workflows/qa-agent.yml` template.
|
|
29
30
|
- **Implementation agent handle:** e.g., `@google-labs-jules`, or "none".
|
|
30
31
|
3. Generate and write the missing files replacing the `{{SCREAMING_SNAKE_CASE}}` placeholders using the templates logic you know (usually they reside in standard Agentic PDLC templates).
|
|
31
32
|
4. Offer to run the `gh` commands for labels (`spec:approved`, `pr:in-review`, `pr:approved`, `architecture-violation`).
|
package/bin/cli.js
CHANGED
|
@@ -63,8 +63,10 @@ rl.question('Which AI Agent will you use for the setup? (e.g. claude, cursor, co
|
|
|
63
63
|
fs.copyFileSync(claudeSetupSrc, dest);
|
|
64
64
|
console.log(`โ
Setup agent profile written to .agentic-setup.md`);
|
|
65
65
|
console.log(`\n${green}๐ Done! To start the conversational setup:${reset}`);
|
|
66
|
-
console.log(`${cyan}\
|
|
67
|
-
console.log(`${cyan}\
|
|
66
|
+
console.log(`${cyan}\tStep 1: Open the Claude Code CLI in your terminal (type 'claude')${reset}`);
|
|
67
|
+
console.log(`${cyan}\t [Or open your preferred IDE Agent chat, like Antigravity, Cursor, Codex, GitHub Copilot, etc]${reset}`);
|
|
68
|
+
console.log(`${cyan}\tStep 2: Paste this exact prompt:${reset}`);
|
|
69
|
+
console.log(`${yellow}\t "read .agentic-setup.md to enter Setup Mode."${reset}`);
|
|
68
70
|
console.log(`\nNote: Once setup is completed, the agent will typically delete .agentic-setup.md to keep your root clean.\n`);
|
|
69
71
|
} else {
|
|
70
72
|
console.error(`โ Could not find claude instruction file at ${claudeSetupSrc}`);
|
package/docs/flow.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
This document describes the full lifecycle of a card on the agentic-pdlc board โ who acts at each stage, what triggers each transition, which labels are added or removed, and where human gates are required.
|
|
4
4
|
|
|
5
|
+
```mermaid
|
|
6
|
+
stateDiagram-v2
|
|
7
|
+
direction LR
|
|
8
|
+
Idea --> Exploration : stage:exploration
|
|
9
|
+
Exploration --> Brainstorming : stage:brainstorming
|
|
10
|
+
Brainstorming --> Detailing : Gate 1 (PM)
|
|
11
|
+
Detailing --> Approval : stage:approval
|
|
12
|
+
Approval --> Development : Gate 2 (spec:approved)
|
|
13
|
+
Development --> Testing : stage:testing
|
|
14
|
+
Testing --> CodeReview : PR Opened
|
|
15
|
+
CodeReview --> Production : Gate 3 (PR Merged)
|
|
16
|
+
```
|
|
17
|
+
|
|
5
18
|
---
|
|
6
19
|
|
|
7
20
|
## Roles
|
|
@@ -21,17 +34,17 @@ This document describes the full lifecycle of a card on the agentic-pdlc board
|
|
|
21
34
|
## Step-by-Step Flow
|
|
22
35
|
|
|
23
36
|
### ๐ก Idea
|
|
24
|
-
Issue exists in the backlog with no `
|
|
37
|
+
Issue exists in the backlog with no `stage:` label.
|
|
25
38
|
|
|
26
39
|
---
|
|
27
40
|
|
|
28
41
|
### ๐ Exploration
|
|
29
42
|
|
|
30
43
|
**Trigger (two equivalent paths):**
|
|
31
|
-
- PM tells Claude directly in chat โ Claude adds `
|
|
32
|
-
- PM adds `
|
|
44
|
+
- PM tells Claude directly in chat โ Claude adds `stage:exploration` to the issue, OR
|
|
45
|
+
- PM adds `stage:exploration` directly to the issue
|
|
33
46
|
|
|
34
|
-
**Workflow:** `project-automation.yml` detects `
|
|
47
|
+
**Workflow:** `project-automation.yml` detects `stage:exploration` โ moves card to Exploration.
|
|
35
48
|
|
|
36
49
|
**Who works:** Claude reads relevant code and context.
|
|
37
50
|
|
|
@@ -43,7 +56,7 @@ Issue exists in the backlog with no `upstream:` label.
|
|
|
43
56
|
|
|
44
57
|
**Actions:**
|
|
45
58
|
- Claude posts a comment on the issue with findings and 2โ3 proposed approaches
|
|
46
|
-
- Claude swaps `
|
|
59
|
+
- Claude swaps `stage:exploration` โ `stage:brainstorming`
|
|
47
60
|
|
|
48
61
|
**Workflow:** `project-automation.yml` moves card to Brainstorming.
|
|
49
62
|
|
|
@@ -57,14 +70,14 @@ Issue exists in the backlog with no `upstream:` label.
|
|
|
57
70
|
|
|
58
71
|
### ๐ Detail Solution โ Gate 1
|
|
59
72
|
|
|
60
|
-
**Trigger:** `upstream-gate.yml` detects PM approval comment on a `
|
|
73
|
+
**Trigger:** `upstream-gate.yml` detects PM approval comment on a `stage:brainstorming` issue โ swaps `stage:brainstorming` โ `stage:detailing` via `PROJECT_TOKEN`.
|
|
61
74
|
|
|
62
75
|
**Who works:** Claude rewrites the issue body with:
|
|
63
76
|
1. User story (`Asโฆ I wantโฆ So thatโฆ`)
|
|
64
77
|
2. Acceptance Criteria (AC1, AC2, โฆ)
|
|
65
78
|
3. Files to modify
|
|
66
79
|
|
|
67
|
-
**After spec is written:** Claude swaps `
|
|
80
|
+
**After spec is written:** Claude swaps `stage:detailing` โ `stage:approval`.
|
|
68
81
|
|
|
69
82
|
**Workflow:** `project-automation.yml` moves card to Approval.
|
|
70
83
|
|
|
@@ -75,8 +88,8 @@ Issue exists in the backlog with no `upstream:` label.
|
|
|
75
88
|
**โธ Human gate (Gate 2 โ PM + TL):** Both PM (business decisions) and TL (technical decisions) review the spec. When both are satisfied, PM adds label `spec:approved`.
|
|
76
89
|
|
|
77
90
|
**Workflow:** `agent-trigger.yml` detects `spec:approved` โ
|
|
78
|
-
1. Removes `
|
|
79
|
-
2. Adds `
|
|
91
|
+
1. Removes `stage:approval`
|
|
92
|
+
2. Adds `stage:development`
|
|
80
93
|
3. Adds specific agent label (e.g., `jules`)
|
|
81
94
|
4. Posts a structured comment with implementation instructions for the Agent
|
|
82
95
|
|
|
@@ -88,7 +101,7 @@ Issue exists in the backlog with no `upstream:` label.
|
|
|
88
101
|
|
|
89
102
|
**Who works:** Implementation Agent implements the spec strictly within the Acceptance Criteria.
|
|
90
103
|
|
|
91
|
-
**When done:** Agent adds `
|
|
104
|
+
**When done:** Agent adds `stage:testing` before running tests.
|
|
92
105
|
|
|
93
106
|
**Workflow:** `project-automation.yml` moves card to Testing.
|
|
94
107
|
|
|
@@ -128,12 +141,12 @@ Issue exists in the backlog with no `upstream:` label.
|
|
|
128
141
|
|
|
129
142
|
| Label | Added by | Removed by |
|
|
130
143
|
|-------|----------|------------|
|
|
131
|
-
| `
|
|
132
|
-
| `
|
|
133
|
-
| `
|
|
134
|
-
| `
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
144
|
+
| `stage:exploration` | PM (human) or Claude | Claude |
|
|
145
|
+
| `stage:brainstorming` | Claude | `upstream-gate.yml` |
|
|
146
|
+
| `stage:detailing` | `upstream-gate.yml` | Claude |
|
|
147
|
+
| `stage:approval` | Claude | `agent-trigger.yml` |
|
|
148
|
+
| `stage:development` | `agent-trigger.yml` | Impl. Agent |
|
|
149
|
+
| `stage:testing` | Impl. Agent | `project-automation.yml` (on PR open) |
|
|
137
150
|
| `spec:approved` | PM (human) | โ |
|
|
138
151
|
| `agent_label` (e.g. `jules`, `sweep`) | `agent-trigger.yml` | โ |
|
|
139
152
|
| `pr:in-review` | `project-automation.yml` | `project-automation.yml` |
|
package/docs/pdlc.md
CHANGED
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
| โ๏ธ Development | Agent implementing the spec | Label `stage:development` |
|
|
13
13
|
| ๐งช Testing | CI pipeline running | GitHub Actions |
|
|
14
14
|
| ๐ Code Review / PR | PR opened, awaiting human review | GitHub Actions |
|
|
15
|
-
| ๐ Merge | PR approved, awaiting merge | GitHub Actions |
|
|
16
15
|
| ๐ Production | Merged | GitHub Actions |
|
|
17
16
|
|
|
18
17
|
<!--
|
|
@@ -40,7 +39,6 @@ REPO = {{REPO_OWNER}}/{{REPO_NAME}}
|
|
|
40
39
|
| โ๏ธ Development | `{{ID_DEVELOPMENT}}` |
|
|
41
40
|
| ๐งช Testing | `{{ID_TESTING}}` |
|
|
42
41
|
| ๐ Code Review / PR | `{{ID_CODE_REVIEW_PR}}` |
|
|
43
|
-
| ๐ Merge | `{{ID_MERGE}}` |
|
|
44
42
|
| ๐ Production | `{{ID_PRODUCTION}}` |
|
|
45
43
|
|
|
46
44
|
## Agent ร Phase Mapping
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-agentic-pdlc",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.0.3",
|
|
4
|
+
"description": "Agentic PDLC Framework - Conversational setup for your AI coding assistants",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"bin": {
|
|
7
7
|
"create-agentic-pdlc": "./bin/cli.js"
|
|
@@ -20,7 +20,7 @@ jobs:
|
|
|
20
20
|
PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
|
|
21
21
|
steps:
|
|
22
22
|
- name: Update Labels
|
|
23
|
-
if: ${{ env.PROJECT_TOKEN != '' }}
|
|
23
|
+
if: ${{ env.PROJECT_TOKEN != '' && !contains('{{IMPLEMENTATION_AGENT_LABEL}}', '{{') }}
|
|
24
24
|
uses: actions/github-script@v7
|
|
25
25
|
with:
|
|
26
26
|
github-token: ${{ env.PROJECT_TOKEN }}
|
|
@@ -33,20 +33,21 @@ jobs:
|
|
|
33
33
|
owner,
|
|
34
34
|
repo,
|
|
35
35
|
issue_number,
|
|
36
|
-
name: '
|
|
36
|
+
name: 'stage:approval'
|
|
37
37
|
});
|
|
38
38
|
} catch (error) {
|
|
39
|
-
console.log('Label
|
|
39
|
+
console.log('Label stage:approval not found or could not be removed');
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
await github.rest.issues.addLabels({
|
|
43
43
|
owner,
|
|
44
44
|
repo,
|
|
45
45
|
issue_number,
|
|
46
|
-
labels: ['
|
|
46
|
+
labels: ['stage:development', '{{IMPLEMENTATION_AGENT_LABEL}}', 'agent:working']
|
|
47
47
|
});
|
|
48
48
|
|
|
49
49
|
- name: Comment on issue to trigger agent and prevent race conditions
|
|
50
|
+
if: ${{ !contains('{{IMPLEMENTATION_AGENT_LABEL}}', '{{') }}
|
|
50
51
|
uses: actions/github-script@v7
|
|
51
52
|
with:
|
|
52
53
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -89,6 +90,7 @@ jobs:
|
|
|
89
90
|
contents: read
|
|
90
91
|
steps:
|
|
91
92
|
- name: Comment on issue to trigger agent
|
|
93
|
+
if: ${{ !contains('{{IMPLEMENTATION_AGENT_LABEL}}', '{{') }}
|
|
92
94
|
uses: actions/github-script@v7
|
|
93
95
|
with:
|
|
94
96
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: Auto Approve PRs
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
types: [opened, labeled, synchronize]
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
pull-requests: write
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
auto-approve:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
if: contains(github.event.pull_request.labels.*.name, 'auto-approve')
|
|
13
|
+
steps:
|
|
14
|
+
- uses: hmarr/auto-approve-action@v4
|
|
15
|
+
with:
|
|
16
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -20,13 +20,21 @@ jobs:
|
|
|
20
20
|
run: echo "Replace this with your package manager install command"
|
|
21
21
|
|
|
22
22
|
- name: Run Linters
|
|
23
|
-
|
|
23
|
+
if: ${{ !contains('{{LINT_COMMAND}}', '{{') }}
|
|
24
|
+
run: |
|
|
25
|
+
{{LINT_COMMAND}}
|
|
24
26
|
|
|
25
27
|
- name: Typecheck
|
|
26
|
-
|
|
28
|
+
if: ${{ !contains('{{TYPECHECK_COMMAND}}', '{{') }}
|
|
29
|
+
run: |
|
|
30
|
+
{{TYPECHECK_COMMAND}}
|
|
27
31
|
|
|
28
32
|
- name: Build
|
|
29
|
-
|
|
33
|
+
if: ${{ !contains('{{BUILD_COMMAND}}', '{{') }}
|
|
34
|
+
run: |
|
|
35
|
+
{{BUILD_COMMAND}}
|
|
30
36
|
|
|
31
37
|
- name: Run Tests
|
|
32
|
-
|
|
38
|
+
if: ${{ !contains('{{TEST_COMMAND}}', '{{') }}
|
|
39
|
+
run: |
|
|
40
|
+
{{TEST_COMMAND}}
|
|
@@ -11,6 +11,7 @@ on:
|
|
|
11
11
|
env:
|
|
12
12
|
PROJECT_ID: "{{PROJECT_ID}}"
|
|
13
13
|
STATUS_FIELD_ID: "{{STATUS_FIELD_ID}}"
|
|
14
|
+
STATUS_IDEA: "{{ID_IDEA}}"
|
|
14
15
|
STATUS_EXPLORATION: "{{ID_EXPLORATION}}"
|
|
15
16
|
STATUS_BRAINSTORMING: "{{ID_BRAINSTORMING}}"
|
|
16
17
|
STATUS_DETAILING: "{{ID_DETAILING}}"
|
|
@@ -30,7 +31,7 @@ jobs:
|
|
|
30
31
|
PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
|
|
31
32
|
steps:
|
|
32
33
|
- name: Detect Label and Move Issue
|
|
33
|
-
if: ${{ env.PROJECT_TOKEN != '' }}
|
|
34
|
+
if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
|
|
34
35
|
uses: actions/github-script@v7
|
|
35
36
|
with:
|
|
36
37
|
github-token: ${{ env.PROJECT_TOKEN }}
|
|
@@ -39,28 +40,28 @@ jobs:
|
|
|
39
40
|
let targetStatusId = null;
|
|
40
41
|
let stageName = null;
|
|
41
42
|
|
|
42
|
-
if (labelName === '
|
|
43
|
+
if (labelName === 'stage:exploration') {
|
|
43
44
|
targetStatusId = process.env.STATUS_EXPLORATION;
|
|
44
45
|
stageName = 'Exploration';
|
|
45
|
-
} else if (labelName === '
|
|
46
|
+
} else if (labelName === 'stage:brainstorming') {
|
|
46
47
|
targetStatusId = process.env.STATUS_BRAINSTORMING;
|
|
47
48
|
stageName = 'Brainstorming';
|
|
48
|
-
} else if (labelName === '
|
|
49
|
+
} else if (labelName === 'stage:detailing') {
|
|
49
50
|
targetStatusId = process.env.STATUS_DETAILING;
|
|
50
51
|
stageName = 'Detailing';
|
|
51
|
-
} else if (labelName === '
|
|
52
|
+
} else if (labelName === 'stage:approval') {
|
|
52
53
|
targetStatusId = process.env.STATUS_APPROVAL;
|
|
53
54
|
stageName = 'Approval';
|
|
54
|
-
} else if (labelName === '
|
|
55
|
+
} else if (labelName === 'stage:development') {
|
|
55
56
|
targetStatusId = process.env.STATUS_DEVELOPMENT;
|
|
56
57
|
stageName = 'Development';
|
|
57
|
-
} else if (labelName === '
|
|
58
|
+
} else if (labelName === 'stage:testing') {
|
|
58
59
|
targetStatusId = process.env.STATUS_TESTING;
|
|
59
60
|
stageName = 'Testing';
|
|
60
61
|
}
|
|
61
62
|
|
|
62
63
|
if (!targetStatusId) {
|
|
63
|
-
console.log('No
|
|
64
|
+
console.log('No stage PDLC label found. Skipping.');
|
|
64
65
|
return;
|
|
65
66
|
}
|
|
66
67
|
|
|
@@ -86,9 +87,36 @@ jobs:
|
|
|
86
87
|
await moveItem(node_id, targetStatusId);
|
|
87
88
|
console.log(`Issue #${number} moved to ${stageName}`);
|
|
88
89
|
|
|
89
|
-
|
|
90
|
+
# OPTIONAL: Uncomment to enable architecture-violation โ Idea
|
|
91
|
+
# move-violation-to-board:
|
|
92
|
+
# name: architecture-violation โ ๐ก Idea
|
|
93
|
+
# if: github.event_name == 'issues' && github.event.action == 'labeled' && github.event.label.name == 'architecture-violation'
|
|
94
|
+
# runs-on: ubuntu-latest
|
|
95
|
+
# steps:
|
|
96
|
+
# - name: Move issue to Idea
|
|
97
|
+
# if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
|
|
98
|
+
# uses: actions/github-script@v7
|
|
99
|
+
# with:
|
|
100
|
+
# github-token: ${{ env.PROJECT_TOKEN }}
|
|
101
|
+
# script: |
|
|
102
|
+
# const { issue: { number, node_id } } = context.payload;
|
|
103
|
+
# const { addProjectV2ItemById: { item } } = await github.graphql(`
|
|
104
|
+
# mutation($p: ID!, $c: ID!) {
|
|
105
|
+
# addProjectV2ItemById(input: {projectId: $p, contentId: $c}) { item { id } }
|
|
106
|
+
# }`, { p: process.env.PROJECT_ID, c: node_id });
|
|
107
|
+
# await github.graphql(`
|
|
108
|
+
# mutation($p: ID!, $i: ID!, $f: ID!, $v: ProjectV2FieldValue!) {
|
|
109
|
+
# updateProjectV2ItemFieldValue(input: {projectId: $p, itemId: $i, fieldId: $f, value: $v}) {
|
|
110
|
+
# projectV2Item { id }
|
|
111
|
+
# }
|
|
112
|
+
# }`, {
|
|
113
|
+
# p: process.env.PROJECT_ID, i: item.id, f: process.env.STATUS_FIELD_ID,
|
|
114
|
+
# v: { singleSelectOptionId: process.env.STATUS_IDEA }
|
|
115
|
+
# });
|
|
116
|
+
# console.log(`Issue #${number} moved to Idea`);
|
|
90
117
|
|
|
91
118
|
# PR Opened โ Move linked issue to Code Review / PR
|
|
119
|
+
# ๐ก VARIANT B (QA Agent): If using an AI QA agent, change `STATUS_CODE_REVIEW_PR` to `STATUS_TESTING` on line ~158
|
|
92
120
|
move-card-on-pr-open:
|
|
93
121
|
name: Open PR โ Code Review / PR
|
|
94
122
|
if: github.event_name == 'pull_request' && (github.event.action == 'opened' || github.event.action == 'reopened')
|
|
@@ -97,7 +125,7 @@ jobs:
|
|
|
97
125
|
PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
|
|
98
126
|
steps:
|
|
99
127
|
- name: Move linked issue to Code Review / PR
|
|
100
|
-
if: ${{ env.PROJECT_TOKEN != '' }}
|
|
128
|
+
if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
|
|
101
129
|
uses: actions/github-script@v7
|
|
102
130
|
with:
|
|
103
131
|
github-token: ${{ env.PROJECT_TOKEN }}
|
|
@@ -151,7 +179,7 @@ jobs:
|
|
|
151
179
|
PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
|
|
152
180
|
steps:
|
|
153
181
|
- name: Swap PR labels
|
|
154
|
-
if: ${{ env.PROJECT_TOKEN != '' }}
|
|
182
|
+
if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
|
|
155
183
|
uses: actions/github-script@v7
|
|
156
184
|
with:
|
|
157
185
|
github-token: ${{ env.PROJECT_TOKEN }}
|
|
@@ -170,7 +198,7 @@ jobs:
|
|
|
170
198
|
PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
|
|
171
199
|
steps:
|
|
172
200
|
- name: Move issue to Production
|
|
173
|
-
if: ${{ env.PROJECT_TOKEN != '' }}
|
|
201
|
+
if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
|
|
174
202
|
uses: actions/github-script@v7
|
|
175
203
|
with:
|
|
176
204
|
github-token: ${{ env.PROJECT_TOKEN }}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: Protect Workflows
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
types: [opened, synchronize, reopened, labeled]
|
|
6
|
+
paths:
|
|
7
|
+
- '.github/**'
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
block-unauthorized-edits:
|
|
11
|
+
name: Protect .github directory
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- name: Check for Human Approval
|
|
15
|
+
if: ${{ !contains(github.event.pull_request.labels.*.name, 'human-approved') }}
|
|
16
|
+
run: |
|
|
17
|
+
echo "๐จ Modifications in the .github/ directory detected."
|
|
18
|
+
echo "As a security measure, this repository blocks workflow edits by default."
|
|
19
|
+
echo "If you are an AI Agent, do not add the approval label yourself."
|
|
20
|
+
echo "If you are the human owner, please add the 'human-approved' label to this PR to allow merging."
|
|
21
|
+
exit 1
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: AI QA Agent
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
types: [opened, synchronize, reopened]
|
|
5
|
+
|
|
6
|
+
permissions:
|
|
7
|
+
pull-requests: write
|
|
8
|
+
contents: read
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
qa:
|
|
12
|
+
name: Run AI QA Agent
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
- name: Execute QA Tests
|
|
17
|
+
run: |
|
|
18
|
+
echo "Run your QA Agent here."
|
|
19
|
+
echo "This could be QAWolf, a custom LLM script, or a secondary agent."
|
|
20
|
+
echo "If tests pass: gh pr edit $PR_URL --add-label 'qa:pass'"
|
|
21
|
+
echo "If tests fail: gh pr edit $PR_URL --add-label 'qa:fail'"
|
|
22
|
+
|
|
23
|
+
# Example success:
|
|
24
|
+
# gh pr edit ${{ github.event.pull_request.html_url }} --add-label "qa:pass"
|
|
25
|
+
env:
|
|
26
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
27
|
+
PR_URL: ${{ github.event.pull_request.html_url }}
|
package/templates/AGENTS.md
CHANGED
|
@@ -30,13 +30,14 @@ Always start from the current `main` HEAD. Never work over stale snapshots.
|
|
|
30
30
|
## Mandatory Workflow
|
|
31
31
|
|
|
32
32
|
0. **Identity**: Always prefix your GitHub comments with `๐ค **Agent:** ` to distinguish yourself.
|
|
33
|
-
1.
|
|
34
|
-
2. Read
|
|
35
|
-
3. Read
|
|
36
|
-
4.
|
|
37
|
-
5.
|
|
38
|
-
6. Run
|
|
39
|
-
7.
|
|
33
|
+
1. **Initial State**: When beginning work on a new issue, your very first action must be to apply the `stage:exploration` label using the GitHub CLI (`gh issue edit <N> --add-label "stage:exploration"`).
|
|
34
|
+
2. Read the issue entirely โ understand its type (US/BUG/TASK/SPIKE) and the Acceptance Criteria.
|
|
35
|
+
3. Read `docs/pdlc.md` โ understand the PDLC and the Definition of Done in this project.
|
|
36
|
+
4. Read all files mentioned in the issue's technical context.
|
|
37
|
+
5. Implement the **minimum viable change** that satisfies the ACs โ do not refactor beyond scope.
|
|
38
|
+
6. Run tests: `{{TEST_COMMAND}}`
|
|
39
|
+
7. Run typecheck (if applicable): `{{TYPECHECK_COMMAND}}`
|
|
40
|
+
8. Create a Pull Request with `Closes #N` in the body โ automation moves the board.
|
|
40
41
|
|
|
41
42
|
### Spec format (Upstream Agents)
|
|
42
43
|
|
package/templates/docs/pdlc.md
CHANGED
|
@@ -10,9 +10,8 @@
|
|
|
10
10
|
| ๐ Detail Solution | Claude is writing the technical spec | Label `stage:detailing` |
|
|
11
11
|
| โ
Approval | Spec ready, awaiting `spec:approved` label | Label `spec:approved` |
|
|
12
12
|
| โ๏ธ Development | Agent implementing the spec | Label `stage:development` |
|
|
13
|
-
| ๐งช Testing | CI pipeline running | GitHub Actions |
|
|
14
|
-
| ๐ Code Review / PR | PR opened
|
|
15
|
-
| ๐ Merge | PR approved, awaiting merge | GitHub Actions |
|
|
13
|
+
| ๐งช Testing | CI pipeline or AI QA Agent running (Variant B) | GitHub Actions / QA Agent |
|
|
14
|
+
| ๐ Code Review / PR | PR opened (Variant A) or QA passed (Variant B) | GitHub Actions |
|
|
16
15
|
| ๐ Production | Merged | GitHub Actions |
|
|
17
16
|
|
|
18
17
|
<!--
|
|
@@ -20,6 +19,11 @@ Adapt columns as needed. The functional baseline is:
|
|
|
20
19
|
๐ก Idea โ โ๏ธ Development โ ๐ Code Review / PR โ ๐ Production
|
|
21
20
|
-->
|
|
22
21
|
|
|
22
|
+
## Workflow Variants (QA Agent)
|
|
23
|
+
|
|
24
|
+
- **Variant A (Default):** PRs bypass the `Testing` column and land directly in `Code Review / PR`.
|
|
25
|
+
- **Variant B (QA Agent Enabled):** PRs land in the `Testing` column first. An AI QA agent verifies the PR, adding `qa:pass` or `qa:fail`. Only after a `qa:pass` is the issue moved to `Code Review / PR`.
|
|
26
|
+
|
|
23
27
|
## Board Identifiers (GitHub Projects)
|
|
24
28
|
|
|
25
29
|
```
|
|
@@ -40,7 +44,6 @@ REPO = {{REPO_OWNER}}/{{REPO_NAME}}
|
|
|
40
44
|
| โ๏ธ Development | `{{ID_DEVELOPMENT}}` |
|
|
41
45
|
| ๐งช Testing | `{{ID_TESTING}}` |
|
|
42
46
|
| ๐ Code Review / PR | `{{ID_CODE_REVIEW_PR}}` |
|
|
43
|
-
| ๐ Merge | `{{ID_MERGE}}` |
|
|
44
47
|
| ๐ Production | `{{ID_PRODUCTION}}` |
|
|
45
48
|
|
|
46
49
|
## Agent ร Phase Mapping
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
name: Upstream Gate 1
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
issue_comment:
|
|
5
|
-
types: [created]
|
|
6
|
-
|
|
7
|
-
jobs:
|
|
8
|
-
evaluate-gate:
|
|
9
|
-
name: Evaluate Brainstorming Approval
|
|
10
|
-
if: ${{ !github.event.issue.pull_request && contains(github.event.issue.labels.*.name, 'upstream:brainstorming') }}
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
env:
|
|
13
|
-
PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
|
|
14
|
-
steps:
|
|
15
|
-
- name: Check for approval and swap label
|
|
16
|
-
if: ${{ env.PROJECT_TOKEN != '' }}
|
|
17
|
-
uses: actions/github-script@v7
|
|
18
|
-
with:
|
|
19
|
-
github-token: ${{ env.PROJECT_TOKEN }}
|
|
20
|
-
script: |
|
|
21
|
-
const comment = context.payload.comment.body.toLowerCase();
|
|
22
|
-
const isApproved =
|
|
23
|
-
comment.includes('approved') ||
|
|
24
|
-
comment.includes('lgtm') ||
|
|
25
|
-
/option\s+[a-z0-9]/i.test(comment) ||
|
|
26
|
-
/go\s+with\s+[a-z0-9]/i.test(comment) ||
|
|
27
|
-
/proceed/i.test(comment);
|
|
28
|
-
|
|
29
|
-
if (isApproved) {
|
|
30
|
-
const { owner, repo } = context.repo;
|
|
31
|
-
const issue_number = context.payload.issue.number;
|
|
32
|
-
|
|
33
|
-
console.log('Approval detected, swapping labels...');
|
|
34
|
-
|
|
35
|
-
try {
|
|
36
|
-
await github.rest.issues.removeLabel({
|
|
37
|
-
owner,
|
|
38
|
-
repo,
|
|
39
|
-
issue_number,
|
|
40
|
-
name: 'upstream:brainstorming'
|
|
41
|
-
});
|
|
42
|
-
} catch (e) {
|
|
43
|
-
console.log('Could not remove upstream:brainstorming label');
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
await github.rest.issues.addLabels({
|
|
47
|
-
owner,
|
|
48
|
-
repo,
|
|
49
|
-
issue_number,
|
|
50
|
-
labels: ['upstream:detailing']
|
|
51
|
-
});
|
|
52
|
-
} else {
|
|
53
|
-
console.log('No approval pattern detected in the comment.');
|
|
54
|
-
}
|