create-agentic-pdlc 2.1.3 → 2.1.4

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.
@@ -42,7 +42,7 @@ If any of these files are missing, you are in **Setup Mode**. Do not proceed wit
42
42
  - c) **Yes, activate** — *Uncomment the `move-violation-to-board` job in `project-automation.yml`.* → Activate immediately.
43
43
  - **QA Agent:** Ask: *"Do you want to use a QA agent to verify PRs automatically before Code Review?"* Present the options:
44
44
  - a) **No (Variant A)** — *PRs go straight to Code Review. Standard and simpler.*
45
- - b) **Yes (Variant B), but I need help configuring it** — *PRs pass through a QA Agent before being reviewed. Requires a QA Agent (e.g., QAWolf).* → Guide the user through configuration.
45
+ - b) **Yes (Variant B), but I need help configuring it** — *PRs pass through a QA Agent before being reviewed. Requires a `GEMINI_API_KEY` secret (free tier available at ai.google.dev).* → Guide the user through configuration.
46
46
  - c) **Yes (Variant B), I already have it configured** — *PRs pass through a QA Agent before being reviewed.* → Activate Variant B immediately: change `STATUS_CODE_REVIEW_PR` to `STATUS_TESTING` in the `move-card-on-pr-open` job and uncomment the `move-card-on-qa-pass` job in `project-automation.yml`.
47
47
  - **Implementation Agent:** Ask: *"Do you use an autonomous implementation agent? (It implements the features you approve for development)"* Present the options:
48
48
  - a) **No** — *No autonomous implementation agent.*
package/bin/cli.js CHANGED
@@ -159,6 +159,7 @@ async function runSetup() {
159
159
  { name: 'architecture-violation', color: 'd93f0b', description: 'Invariant violation detected by CI' },
160
160
  { name: 'qa:approved', color: '0e8a16', description: 'QA Agent approved the implementation' },
161
161
  { name: 'qa:needs-work', color: 'd93f0b', description: 'QA Agent found issues' },
162
+ { name: 'infra:qa-broken', color: 'F97316', description: 'QA Agent failed to run — manual review required' },
162
163
  { name: 'jules', color: '5319e7', description: 'Jules AI Agent' }
163
164
  ];
164
165
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-agentic-pdlc",
3
- "version": "2.1.3",
3
+ "version": "2.1.4",
4
4
  "description": "Agentic PDLC Framework - Conversational setup for your AI coding assistants",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -2,7 +2,7 @@ name: PDLC Board Automation
2
2
 
3
3
  on:
4
4
  pull_request:
5
- types: [opened, reopened, closed]
5
+ types: [opened, reopened, closed, labeled]
6
6
  pull_request_review:
7
7
  types: [submitted]
8
8
  issues:
@@ -189,6 +189,52 @@ jobs:
189
189
  try { await github.rest.issues.removeLabel({ owner, repo, issue_number: prNumber, name: 'pr:in-review' }); } catch {}
190
190
  await github.rest.issues.addLabels({ owner, repo, issue_number: prNumber, labels: ['pr:approved'] }).catch(() => {});
191
191
 
192
+ # OPTIONAL: Uncomment for Variant B (QA Agent enabled)
193
+ # When qa:approved is added to a PR, move linked issue to Code Review / PR
194
+ # move-card-on-qa-pass:
195
+ # name: qa:approved → Code Review / PR
196
+ # if: github.event_name == 'pull_request' && github.event.action == 'labeled' && github.event.label.name == 'qa:approved'
197
+ # runs-on: ubuntu-latest
198
+ # env:
199
+ # PROJECT_PAT: ${{ secrets.PROJECT_PAT }}
200
+ # steps:
201
+ # - name: Move linked issue to Code Review / PR
202
+ # if: ${{ env.PROJECT_PAT != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
203
+ # uses: actions/github-script@v7
204
+ # with:
205
+ # github-token: ${{ env.PROJECT_PAT }}
206
+ # script: |
207
+ # const prNumber = context.payload.pull_request.number;
208
+ # const { owner, repo } = context.repo;
209
+ # const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number: prNumber });
210
+ # const body = pr.body ?? '';
211
+ # const linkedIssues = [...body.matchAll(/(?:Closes?|Fixes?|Resolves?)\s+#(\d+)/gi)].map(m => parseInt(m[1]));
212
+ # const moveItem = async (nodeId) => {
213
+ # const { addProjectV2ItemById: { item } } = await github.graphql(`
214
+ # mutation($p: ID!, $c: ID!) {
215
+ # addProjectV2ItemById(input: {projectId: $p, contentId: $c}) { item { id } }
216
+ # }`, { p: process.env.PROJECT_ID, c: nodeId });
217
+ # await github.graphql(`
218
+ # mutation($p: ID!, $i: ID!, $f: ID!, $v: ProjectV2FieldValue!) {
219
+ # updateProjectV2ItemFieldValue(input: {projectId: $p, itemId: $i, fieldId: $f, value: $v}) {
220
+ # projectV2Item { id }
221
+ # }
222
+ # }`, {
223
+ # p: process.env.PROJECT_ID, i: item.id, f: process.env.STATUS_FIELD_ID,
224
+ # v: { singleSelectOptionId: process.env.STATUS_CODE_REVIEW_PR }
225
+ # });
226
+ # };
227
+ # if (linkedIssues.length > 0) {
228
+ # for (const n of linkedIssues) {
229
+ # const { data: issue } = await github.rest.issues.get({ owner, repo, issue_number: n });
230
+ # await moveItem(issue.node_id);
231
+ # console.log(`Issue #${n} → Code Review / PR`);
232
+ # }
233
+ # } else {
234
+ # await moveItem(pr.node_id);
235
+ # console.log(`PR #${prNumber} → Code Review / PR (no linked issue)`);
236
+ # }
237
+
192
238
  # PR Merged → Production
193
239
  move-card-on-pr-merge:
194
240
  name: Merged PR → Production
@@ -6,22 +6,73 @@ on:
6
6
  permissions:
7
7
  pull-requests: write
8
8
  contents: read
9
+ issues: read
9
10
 
10
11
  jobs:
11
12
  qa:
12
- name: Run AI QA Agent
13
+ name: AC Coverage Verification (Gemini)
13
14
  runs-on: ubuntu-latest
14
15
  steps:
15
16
  - 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"
17
+ with:
18
+ fetch-depth: 0
19
+
20
+ - name: Verify AC Coverage via Gemini
25
21
  env:
26
22
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
27
- PR_URL: ${{ github.event.pull_request.html_url }}
23
+ GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }}
24
+ run: |
25
+ set -e
26
+
27
+ PR_NUMBER="${{ github.event.pull_request.number }}"
28
+ BASE="${{ github.event.pull_request.base.sha }}"
29
+ HEAD="${{ github.event.pull_request.head.sha }}"
30
+
31
+ # Get PR diff (truncated to 8000 chars to stay within context limits)
32
+ DIFF=$(git diff "$BASE" "$HEAD" | head -c 8000)
33
+
34
+ # Extract linked issues from PR body
35
+ PR_BODY=$(gh pr view "$PR_NUMBER" --json body --jq '.body // ""')
36
+ ISSUE_NUMS=$(echo "$PR_BODY" | grep -oiE '(Closes?|Fixes?|Resolves?)\s+#([0-9]+)' | grep -oE '[0-9]+' || true)
37
+
38
+ # Build acceptance criteria context
39
+ AC_CONTEXT=""
40
+ if [ -n "$ISSUE_NUMS" ]; then
41
+ for NUM in $ISSUE_NUMS; do
42
+ ISSUE_BODY=$(gh issue view "$NUM" --json body --jq '.body // ""' 2>/dev/null || echo "")
43
+ AC_CONTEXT="${AC_CONTEXT}\\n\\n--- Issue #${NUM} ---\\n${ISSUE_BODY}"
44
+ done
45
+ fi
46
+
47
+ if [ -z "$AC_CONTEXT" ]; then
48
+ AC_CONTEXT="No linked issue found. Evaluate if the PR description is self-contained."
49
+ fi
50
+
51
+ # Serialize prompt as JSON string and call Gemini API (30s timeout)
52
+ PROMPT_JSON=$(printf '%s' "You are a senior QA engineer. Review whether this PR diff satisfies the Acceptance Criteria below.\n\nACCEPTANCE CRITERIA:\n${AC_CONTEXT}\n\nPR DIFF:\n${DIFF}\n\nRespond with exactly one word: PASS or FAIL, then on the next line explain briefly why (max 3 sentences)." | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')
53
+
54
+ RESPONSE=$(curl -s -X POST \
55
+ "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${GEMINI_API_KEY}" \
56
+ -H "Content-Type: application/json" \
57
+ -d "{\"contents\":[{\"parts\":[{\"text\":${PROMPT_JSON}}]}]}" \
58
+ --max-time 30 || echo "API_ERROR")
59
+
60
+ if [ "$RESPONSE" = "API_ERROR" ]; then
61
+ gh pr edit "$PR_NUMBER" --add-label "infra:qa-broken"
62
+ gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** Could not reach Gemini API. Manual review required."
63
+ exit 0
64
+ fi
65
+
66
+ VERDICT=$(echo "$RESPONSE" | python3 -c 'import json,sys; d=json.load(sys.stdin); t=d.get("candidates",[{}])[0].get("content",{}).get("parts",[{}])[0].get("text","").strip(); print(t.split("\n")[0].upper() if t else "API_ERROR")')
67
+ EXPLANATION=$(echo "$RESPONSE" | python3 -c 'import json,sys; d=json.load(sys.stdin); t=d.get("candidates",[{}])[0].get("content",{}).get("parts",[{}])[0].get("text","").strip(); lines=t.split("\n",1); print(lines[1].strip() if len(lines)>1 else "")')
68
+
69
+ if echo "$VERDICT" | grep -q "^PASS"; then
70
+ gh pr edit "$PR_NUMBER" --add-label "qa:approved"
71
+ gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** AC coverage verified. ${EXPLANATION}"
72
+ elif echo "$VERDICT" | grep -q "^FAIL"; then
73
+ gh pr edit "$PR_NUMBER" --add-label "qa:needs-work"
74
+ gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** AC coverage insufficient. ${EXPLANATION}"
75
+ else
76
+ gh pr edit "$PR_NUMBER" --add-label "infra:qa-broken"
77
+ gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** Could not parse Gemini response. Manual review required."
78
+ fi
@@ -70,6 +70,7 @@ When detailing a solution in an issue body, you must **always** include both the
70
70
  - Never open a PR without passing the tests.
71
71
  - Never implement beyond the immediate scope of the issue.
72
72
  - Never create future-proofing abstractions for hypothetical features.
73
+ - Never add or remove `stage:*` or `qa:*` labels manually. These are owned by GitHub Actions automation and the PM only.
73
74
  {{EXTRA_DONT}}
74
75
 
75
76
  ## Project Standards
@@ -22,7 +22,7 @@ Adapt columns as needed. The functional baseline is:
22
22
  ## Workflow Variants (QA Agent)
23
23
 
24
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`.
25
+ - **Variant B (QA Agent Enabled):** PRs land in the `Testing` column first. An AI QA agent verifies the PR, adding `qa:approved` or `qa:needs-work`. Only after a `qa:approved` is the issue moved to `Code Review / PR`.
26
26
 
27
27
  ## Board Identifiers (GitHub Projects)
28
28
 
@@ -77,6 +77,9 @@ REPO = {{REPO_OWNER}}/{{REPO_NAME}}
77
77
  | `spec:approved` | Issue | Green | Gate 2 — agent is cleared to implement |
78
78
  | `pr:in-review` | PR | Yellow | Awaiting code review |
79
79
  | `pr:approved` | PR | Green | Code review approved |
80
+ | `qa:approved` | PR | Green | QA Agent passed — AC coverage verified |
81
+ | `qa:needs-work` | PR | Red | QA Agent failed — PR needs changes |
82
+ | `infra:qa-broken` | PR | Orange | QA Agent error — manual review required |
80
83
 
81
84
  ## Approval Gates
82
85