create-agentic-pdlc 2.0.1 โ†’ 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.
@@ -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: 'upstream:approval'
36
+ name: 'stage:approval'
37
37
  });
38
38
  } catch (error) {
39
- console.log('Label upstream:approval not found or could not be removed');
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: ['upstream:development', '{{IMPLEMENTATION_AGENT_LABEL}}', 'agent:working']
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
- run: echo "No tests/build needed."
23
+ if: ${{ !contains('{{LINT_COMMAND}}', '{{') }}
24
+ run: |
25
+ {{LINT_COMMAND}}
24
26
 
25
27
  - name: Typecheck
26
- run: echo "No typecheck needed."
28
+ if: ${{ !contains('{{TYPECHECK_COMMAND}}', '{{') }}
29
+ run: |
30
+ {{TYPECHECK_COMMAND}}
27
31
 
28
32
  - name: Build
29
- run: echo "No tests/build needed."
33
+ if: ${{ !contains('{{BUILD_COMMAND}}', '{{') }}
34
+ run: |
35
+ {{BUILD_COMMAND}}
30
36
 
31
37
  - name: Run Tests
32
- run: echo "No tests/build needed."
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 === 'upstream:exploration') {
43
+ if (labelName === 'stage:exploration') {
43
44
  targetStatusId = process.env.STATUS_EXPLORATION;
44
45
  stageName = 'Exploration';
45
- } else if (labelName === 'upstream:brainstorming') {
46
+ } else if (labelName === 'stage:brainstorming') {
46
47
  targetStatusId = process.env.STATUS_BRAINSTORMING;
47
48
  stageName = 'Brainstorming';
48
- } else if (labelName === 'upstream:detailing') {
49
+ } else if (labelName === 'stage:detailing') {
49
50
  targetStatusId = process.env.STATUS_DETAILING;
50
51
  stageName = 'Detailing';
51
- } else if (labelName === 'upstream:approval') {
52
+ } else if (labelName === 'stage:approval') {
52
53
  targetStatusId = process.env.STATUS_APPROVAL;
53
54
  stageName = 'Approval';
54
- } else if (labelName === 'upstream:development') {
55
+ } else if (labelName === 'stage:development') {
55
56
  targetStatusId = process.env.STATUS_DEVELOPMENT;
56
57
  stageName = 'Development';
57
- } else if (labelName === 'upstream:testing') {
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 upstream PDLC label found. Skipping.');
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
- {{OPTIONAL_ARCHITECTURE_VIOLATION_JOB}}
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/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), the Setup Mode can automatically add a GitHub Actions job to `project-automation.yml` that moves these issues to the `Idea` column.
141
-
142
- If you skipped this during setup but want to add it later, you can append the following job to `.github/workflows/project-automation.yml` under the `jobs` section:
143
-
144
- ```yaml
145
- move-violation-to-board:
146
- name: architecture-violation โ†’ ๐Ÿ’ก Idea
147
- if: github.event_name == 'issues' && github.event.label.name == 'architecture-violation'
148
- runs-on: ubuntu-latest
149
- steps:
150
- - uses: actions/github-script@v7
151
- with:
152
- github-token: ${{ secrets.PROJECT_TOKEN }}
153
- script: |
154
- const issueNodeId = context.payload.issue.node_id;
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, Merge, 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, replace `{{OPTIONAL_ARCHITECTURE_VIOLATION_JOB}}` in `project-automation.yml` with the job definition (available in the framework documentation). If no, ask if they would like help implementing one, reminding them that it significantly improves their agentic development process. If they decline, remove the placeholder.
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/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,6 +1,6 @@
1
1
  {
2
2
  "name": "create-agentic-pdlc",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "description": "Agentic PDLC Framework - Conversational setup for your AI coding assistants",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -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: 'upstream:approval'
36
+ name: 'stage:approval'
37
37
  });
38
38
  } catch (error) {
39
- console.log('Label upstream:approval not found or could not be removed');
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: ['upstream:development', '{{IMPLEMENTATION_AGENT_LABEL}}', 'agent:working']
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
- run: {{LINT_COMMAND}}
23
+ if: ${{ !contains('{{LINT_COMMAND}}', '{{') }}
24
+ run: |
25
+ {{LINT_COMMAND}}
24
26
 
25
27
  - name: Typecheck
26
- run: {{TYPECHECK_COMMAND}}
28
+ if: ${{ !contains('{{TYPECHECK_COMMAND}}', '{{') }}
29
+ run: |
30
+ {{TYPECHECK_COMMAND}}
27
31
 
28
32
  - name: Build
29
- run: {{BUILD_COMMAND}}
33
+ if: ${{ !contains('{{BUILD_COMMAND}}', '{{') }}
34
+ run: |
35
+ {{BUILD_COMMAND}}
30
36
 
31
37
  - name: Run Tests
32
- run: {{TEST_COMMAND}}
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 === 'upstream:exploration') {
43
+ if (labelName === 'stage:exploration') {
43
44
  targetStatusId = process.env.STATUS_EXPLORATION;
44
45
  stageName = 'Exploration';
45
- } else if (labelName === 'upstream:brainstorming') {
46
+ } else if (labelName === 'stage:brainstorming') {
46
47
  targetStatusId = process.env.STATUS_BRAINSTORMING;
47
48
  stageName = 'Brainstorming';
48
- } else if (labelName === 'upstream:detailing') {
49
+ } else if (labelName === 'stage:detailing') {
49
50
  targetStatusId = process.env.STATUS_DETAILING;
50
51
  stageName = 'Detailing';
51
- } else if (labelName === 'upstream:approval') {
52
+ } else if (labelName === 'stage:approval') {
52
53
  targetStatusId = process.env.STATUS_APPROVAL;
53
54
  stageName = 'Approval';
54
- } else if (labelName === 'upstream:development') {
55
+ } else if (labelName === 'stage:development') {
55
56
  targetStatusId = process.env.STATUS_DEVELOPMENT;
56
57
  stageName = 'Development';
57
- } else if (labelName === 'upstream:testing') {
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 upstream PDLC label found. Skipping.');
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
- {{OPTIONAL_ARCHITECTURE_VIOLATION_JOB}}
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 }}
@@ -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, awaiting human review | GitHub Actions |
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
- }