create-agentic-pdlc 2.2.1 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/.agentic-pdlc/SETUP_PROMPT.md +3 -4
  2. package/.agentic-pdlc/metrics/raw/2026-W18.jsonl +2 -0
  3. package/.agentic-pdlc/metrics/raw/2026-W21.jsonl +68 -0
  4. package/.agentic-pdlc/metrics/raw/2026-W22.jsonl +114 -0
  5. package/.agentic-setup-prompt.md +3 -4
  6. package/.agentic-setup.md +3 -4
  7. package/.github/ISSUE_TEMPLATE/bug.md +53 -0
  8. package/.github/ISSUE_TEMPLATE/feature.md +54 -0
  9. package/.github/ISSUE_TEMPLATE/task.md +33 -0
  10. package/.github/workflows/add-to-board.yml +1 -1
  11. package/.github/workflows/agent-trigger.yml +4 -4
  12. package/.github/workflows/agentic-metrics.yml +171 -38
  13. package/.github/workflows/ci.yml +1 -1
  14. package/.github/workflows/npm-publish.yml +2 -2
  15. package/.github/workflows/pdlc-health-check.yml +1 -3
  16. package/.github/workflows/pdlc-stage-gate.yml +2 -2
  17. package/.github/workflows/project-automation.yml +79 -16
  18. package/.github/workflows/qa-agent.yml +26 -15
  19. package/.github/workflows/qa-gate.yml +51 -0
  20. package/AGENTS.md +50 -8
  21. package/CLAUDE.md +53 -3
  22. package/SETUP.md +4 -1
  23. package/adapters/claude-code/skill.md +44 -20
  24. package/adapters/hooks/pdlc-stage-gate.sh +2 -7
  25. package/bin/cli.js +41 -9
  26. package/docs/flow.md +8 -21
  27. package/docs/pdlc.md +24 -16
  28. package/docs/superpowers/plans/2026-05-28-jules-label-pat-split.md +240 -0
  29. package/docs/superpowers/plans/2026-05-29-agentic-pulse-rework-taxonomy.md +474 -0
  30. package/docs/superpowers/plans/2026-05-29-qa-gate-enforcement.md +354 -0
  31. package/docs/superpowers/specs/2026-05-29-agentic-pulse-rework-taxonomy-design.md +122 -0
  32. package/package.json +1 -1
  33. package/templates/.github/ISSUE_TEMPLATE/bug.md +53 -0
  34. package/templates/.github/ISSUE_TEMPLATE/feature.md +54 -0
  35. package/templates/.github/ISSUE_TEMPLATE/task.md +33 -0
  36. package/templates/.github/workflows/add-to-board.yml +4 -4
  37. package/templates/.github/workflows/agent-trigger.yml +24 -15
  38. package/{.agentic-pdlc/templates → templates}/.github/workflows/agentic-metrics.yml +166 -36
  39. package/templates/.github/workflows/ci.yml +15 -1
  40. package/templates/.github/workflows/pdlc-health-check.yml +1 -3
  41. package/templates/.github/workflows/pdlc-stage-gate.yml +2 -2
  42. package/templates/.github/workflows/project-automation.yml +93 -36
  43. package/templates/.github/workflows/qa-agent.yml +33 -17
  44. package/templates/.github/workflows/qa-gate.yml +51 -0
  45. package/templates/AGENTS.md +74 -23
  46. package/templates/docs/pdlc.md +24 -16
  47. package/.agentic-pdlc/templates/.github/CODEOWNERS +0 -5
  48. package/.agentic-pdlc/templates/.github/copilot-instructions.md +0 -12
  49. package/.agentic-pdlc/templates/.github/workflows/add-to-board.yml +0 -38
  50. package/.agentic-pdlc/templates/.github/workflows/agent-trigger.yml +0 -146
  51. package/.agentic-pdlc/templates/.github/workflows/auto-approve.yml +0 -16
  52. package/.agentic-pdlc/templates/.github/workflows/ci.yml +0 -40
  53. package/.agentic-pdlc/templates/.github/workflows/pdlc-health-check.yml +0 -123
  54. package/.agentic-pdlc/templates/.github/workflows/pdlc-stage-gate.yml +0 -51
  55. package/.agentic-pdlc/templates/.github/workflows/project-automation.yml +0 -278
  56. package/.agentic-pdlc/templates/.github/workflows/protect-workflows.yml +0 -21
  57. package/.agentic-pdlc/templates/.github/workflows/qa-agent.yml +0 -128
  58. package/.agentic-pdlc/templates/AGENTS.md +0 -81
  59. package/.agentic-pdlc/templates/docs/pdlc.md +0 -115
@@ -6,13 +6,12 @@ on:
6
6
  pull_request_review:
7
7
  types: [submitted]
8
8
  issues:
9
- types: [labeled, edited]
9
+ types: [labeled, edited, closed]
10
10
 
11
11
  env:
12
12
  PROJECT_ID: "{{PROJECT_ID}}"
13
13
  STATUS_FIELD_ID: "{{STATUS_FIELD_ID}}"
14
14
  STATUS_IDEA: "{{ID_IDEA}}"
15
- STATUS_EXPLORATION: "{{ID_EXPLORATION}}"
16
15
  STATUS_BRAINSTORMING: "{{ID_BRAINSTORMING}}"
17
16
  STATUS_DETAILING: "{{ID_DETAILING}}"
18
17
  STATUS_APPROVAL: "{{ID_APPROVAL}}"
@@ -28,22 +27,19 @@ jobs:
28
27
  if: github.event_name == 'issues' && github.event.action == 'labeled'
29
28
  runs-on: ubuntu-latest
30
29
  env:
31
- PROJECT_PAT: ${{ secrets.PROJECT_PAT }}
30
+ PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
32
31
  steps:
33
32
  - name: Detect Label and Move Issue
34
- if: ${{ env.PROJECT_PAT != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
35
- uses: actions/github-script@v7
33
+ if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
34
+ uses: actions/github-script@v8
36
35
  with:
37
- github-token: ${{ env.PROJECT_PAT }}
36
+ github-token: ${{ env.PROJECT_TOKEN }}
38
37
  script: |
39
38
  const labelName = context.payload.label.name;
40
39
  let targetStatusId = null;
41
40
  let stageName = null;
42
41
 
43
- if (labelName === 'stage:exploration') {
44
- targetStatusId = process.env.STATUS_EXPLORATION;
45
- stageName = 'Exploration';
46
- } else if (labelName === 'stage:brainstorming') {
42
+ if (labelName === 'stage:brainstorming') {
47
43
  targetStatusId = process.env.STATUS_BRAINSTORMING;
48
44
  stageName = 'Brainstorming';
49
45
  } else if (labelName === 'stage:detailing') {
@@ -55,9 +51,6 @@ jobs:
55
51
  } else if (labelName === 'stage:development') {
56
52
  targetStatusId = process.env.STATUS_DEVELOPMENT;
57
53
  stageName = 'Development';
58
- } else if (labelName === 'stage:testing') {
59
- targetStatusId = process.env.STATUS_TESTING;
60
- stageName = 'Testing';
61
54
  }
62
55
 
63
56
  if (!targetStatusId) {
@@ -95,13 +88,13 @@ jobs:
95
88
  contains(github.event.issue.labels.*.name, 'stage:detailing')
96
89
  runs-on: ubuntu-latest
97
90
  env:
98
- PROJECT_PAT: ${{ secrets.PROJECT_PAT }}
91
+ PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
99
92
  steps:
100
93
  - name: Check spec markers and swap labels
101
- if: ${{ env.PROJECT_PAT != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
102
- uses: actions/github-script@v7
94
+ if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
95
+ uses: actions/github-script@v8
103
96
  with:
104
- github-token: ${{ env.PROJECT_PAT }}
97
+ github-token: ${{ env.PROJECT_TOKEN }}
105
98
  script: |
106
99
  const body = context.payload.issue.body ?? '';
107
100
  if (!body.includes('## Acceptance Criteria') || !body.includes('## Files to modify')) return;
@@ -113,6 +106,42 @@ jobs:
113
106
  await github.rest.issues.removeLabel({ owner, repo, issue_number, name: 'stage:detailing' }).catch(() => {});
114
107
  console.log(`Issue #${issue_number} auto-moved to stage:approval`);
115
108
 
109
+ # human-approved on issue → qa:approved on linked open PRs
110
+ handle-human-approved:
111
+ name: human-approved → qa:approved on linked PRs
112
+ if: github.event_name == 'issues' && github.event.action == 'labeled' && github.event.label.name == 'human-approved'
113
+ runs-on: ubuntu-latest
114
+ permissions:
115
+ issues: write
116
+ pull-requests: write
117
+ steps:
118
+ - name: Add qa:approved to linked open PRs
119
+ uses: actions/github-script@v8
120
+ with:
121
+ github-token: ${{ secrets.GITHUB_TOKEN }}
122
+ script: |
123
+ const { owner, repo } = context.repo;
124
+ const issueNumber = context.payload.issue.number;
125
+ const pattern = new RegExp(`(?:Closes?|Fixes?|Resolves?)\\s+#${issueNumber}\\b`, 'i');
126
+
127
+ const prs = await github.paginate(github.rest.pulls.list, {
128
+ owner, repo, state: 'open', per_page: 100
129
+ });
130
+
131
+ const linked = prs.filter(pr => pattern.test(pr.body ?? ''));
132
+
133
+ if (linked.length === 0) {
134
+ console.log(`No open PRs linking issue #${issueNumber}. Exiting.`);
135
+ return;
136
+ }
137
+
138
+ for (const pr of linked) {
139
+ await github.rest.issues.addLabels({
140
+ owner, repo, issue_number: pr.number, labels: ['qa:approved']
141
+ }).catch(() => {});
142
+ console.log(`PR #${pr.number} → qa:approved`);
143
+ }
144
+
116
145
  # OPTIONAL: Uncomment to enable architecture-violation → Idea
117
146
  # move-violation-to-board:
118
147
  # name: architecture-violation → 💡 Idea
@@ -120,10 +149,10 @@ jobs:
120
149
  # runs-on: ubuntu-latest
121
150
  # steps:
122
151
  # - name: Move issue to Idea
123
- # if: ${{ env.PROJECT_PAT != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
124
- # uses: actions/github-script@v7
152
+ # if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
153
+ # uses: actions/github-script@v8
125
154
  # with:
126
- # github-token: ${{ env.PROJECT_PAT }}
155
+ # github-token: ${{ env.PROJECT_TOKEN }}
127
156
  # script: |
128
157
  # const { issue: { number, node_id } } = context.payload;
129
158
  # const { addProjectV2ItemById: { item } } = await github.graphql(`
@@ -147,13 +176,13 @@ jobs:
147
176
  if: github.event_name == 'pull_request' && (github.event.action == 'opened' || github.event.action == 'reopened')
148
177
  runs-on: ubuntu-latest
149
178
  env:
150
- PROJECT_PAT: ${{ secrets.PROJECT_PAT }}
179
+ PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
151
180
  steps:
152
181
  - name: Move linked issue to Testing
153
- if: ${{ env.PROJECT_PAT != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
154
- uses: actions/github-script@v7
182
+ if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
183
+ uses: actions/github-script@v8
155
184
  with:
156
- github-token: ${{ env.PROJECT_PAT }}
185
+ github-token: ${{ env.PROJECT_TOKEN }}
157
186
  script: |
158
187
  const prNumber = context.payload.pull_request.number;
159
188
  const { owner, repo } = context.repo;
@@ -201,13 +230,13 @@ jobs:
201
230
  if: github.event_name == 'pull_request' && github.event.action == 'labeled' && github.event.label.name == 'qa:approved'
202
231
  runs-on: ubuntu-latest
203
232
  env:
204
- PROJECT_PAT: ${{ secrets.PROJECT_PAT }}
233
+ PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
205
234
  steps:
206
235
  - name: Move linked issue to Code Review / PR
207
- if: ${{ env.PROJECT_PAT != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
208
- uses: actions/github-script@v7
236
+ if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
237
+ uses: actions/github-script@v8
209
238
  with:
210
- github-token: ${{ env.PROJECT_PAT }}
239
+ github-token: ${{ env.PROJECT_TOKEN }}
211
240
  script: |
212
241
  const prNumber = context.payload.pull_request.number;
213
242
  const { owner, repo } = context.repo;
@@ -233,6 +262,9 @@ jobs:
233
262
  for (const n of linkedIssues) {
234
263
  const { data: issue } = await github.rest.issues.get({ owner, repo, issue_number: n });
235
264
  await moveItem(issue.node_id);
265
+ if (issue.labels?.some(l => l.name === 'stage:testing')) {
266
+ await github.rest.issues.removeLabel({ owner, repo, issue_number: n, name: 'stage:testing' }).catch(() => {});
267
+ }
236
268
  console.log(`Issue #${n} → Code Review / PR`);
237
269
  }
238
270
  } else {
@@ -246,13 +278,13 @@ jobs:
246
278
  if: github.event_name == 'pull_request_review' && github.event.review.state == 'approved'
247
279
  runs-on: ubuntu-latest
248
280
  env:
249
- PROJECT_PAT: ${{ secrets.PROJECT_PAT }}
281
+ PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
250
282
  steps:
251
283
  - name: Swap PR labels
252
- if: ${{ env.PROJECT_PAT != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
253
- uses: actions/github-script@v7
284
+ if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
285
+ uses: actions/github-script@v8
254
286
  with:
255
- github-token: ${{ env.PROJECT_PAT }}
287
+ github-token: ${{ env.PROJECT_TOKEN }}
256
288
  script: |
257
289
  const prNumber = context.payload.pull_request.number;
258
290
  const { owner, repo } = context.repo;
@@ -265,13 +297,13 @@ jobs:
265
297
  if: github.event_name == 'pull_request' && github.event.action == 'closed' && github.event.pull_request.merged == true
266
298
  runs-on: ubuntu-latest
267
299
  env:
268
- PROJECT_PAT: ${{ secrets.PROJECT_PAT }}
300
+ PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
269
301
  steps:
270
302
  - name: Move issue to Production
271
- if: ${{ env.PROJECT_PAT != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
272
- uses: actions/github-script@v7
303
+ if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
304
+ uses: actions/github-script@v8
273
305
  with:
274
- github-token: ${{ env.PROJECT_PAT }}
306
+ github-token: ${{ env.PROJECT_TOKEN }}
275
307
  script: |
276
308
  const prNumber = context.payload.pull_request.number;
277
309
  const { owner, repo } = context.repo;
@@ -297,8 +329,33 @@ jobs:
297
329
  for (const n of linkedIssues) {
298
330
  const { data: issue } = await github.rest.issues.get({ owner, repo, issue_number: n });
299
331
  await moveItem(issue.node_id);
332
+ if (issue.labels?.some(l => l.name === 'stage:approval')) {
333
+ await github.rest.issues.removeLabel({ owner, repo, issue_number: n, name: 'stage:approval' }).catch(() => {});
334
+ }
300
335
  console.log(`Issue #${n} → Production`);
301
336
  }
302
337
  } else {
303
338
  await moveItem(pr.node_id);
304
339
  }
340
+
341
+ cleanup-labels-on-close:
342
+ name: Issue closed → strip stage/agent labels
343
+ if: github.event_name == 'issues' && github.event.action == 'closed'
344
+ runs-on: ubuntu-latest
345
+ steps:
346
+ - name: Remove transient labels
347
+ uses: actions/github-script@v8
348
+ with:
349
+ github-token: ${{ secrets.GITHUB_TOKEN }}
350
+ script: |
351
+ const { owner, repo } = context.repo;
352
+ const issue_number = context.payload.issue.number;
353
+ const toRemove = [
354
+ 'stage:brainstorming', 'stage:detailing',
355
+ 'stage:approval', 'stage:development', 'stage:testing',
356
+ 'qa:needs-work', 'pr:in-review', 'jules'
357
+ ];
358
+ for (const label of toRemove) {
359
+ await github.rest.issues.removeLabel({ owner, repo, issue_number, name: label }).catch(() => {});
360
+ }
361
+ console.log(`Issue #${issue_number} labels cleaned up`);
@@ -13,8 +13,10 @@ jobs:
13
13
  qa:
14
14
  name: AC Coverage Verification (GitHub Models)
15
15
  runs-on: ubuntu-latest
16
+ env:
17
+ PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
16
18
  steps:
17
- - uses: actions/checkout@v4
19
+ - uses: actions/checkout@v5.0.1
18
20
  with:
19
21
  fetch-depth: 0
20
22
 
@@ -29,7 +31,7 @@ jobs:
29
31
  HEAD="${{ github.event.pull_request.head.sha }}"
30
32
 
31
33
  # Get PR diff (truncated to 8000 chars to stay within context limits)
32
- DIFF=$(git diff "$BASE" "$HEAD" | head -c 64000)
34
+ DIFF=$(git diff "$BASE" "$HEAD" | head -c 8000)
33
35
 
34
36
  # Extract linked issues from PR body
35
37
  PR_BODY=$(gh pr view "$PR_NUMBER" --json body --jq '.body // ""')
@@ -49,31 +51,45 @@ jobs:
49
51
  fi
50
52
 
51
53
  # Serialize prompt as JSON string and call GitHub Models 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\nFirst line of your response must be exactly one word: PASS or FAIL. Second line: brief explanation (max 3 sentences)." | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')
54
+ PROMPT_JSON=$(printf '%s' "You are an adversarial product tester. Your mission is to find what the Acceptance Criteria do NOT cover — undefined edge cases, ambiguous states, missing user scenarios. Do NOT review code quality, file structure, or technical consistency.\n\nACCEPTANCE CRITERIA:\n${AC_CONTEXT}\n\nPR DIFF:\n${DIFF}\n\nRespond in exactly 3 lines (do NOT wrap your response in markdown code blocks or any other formatting):\nLine 1: PASS or FAIL (PASS if the PR diff fully satisfies the stated Acceptance Criteria, FAIL if it falls short of covering them)\nLine 2: Gaps: [one-line summary of AC gaps found, or \"none\"]\nLine 3: Not covered: [AC refs where diff falls short, or \"all covered\"]" | python3 -c 'import json,sys; print(json.dumps(sys.stdin.read()))')
53
55
 
54
- RESPONSE=$(curl -sf -X POST \
55
- "https://models.github.ai/inference/chat/completions" \
56
- -H "Authorization: Bearer ${GITHUB_TOKEN}" \
57
- -H "Content-Type: application/json" \
58
- -d "{\"model\":\"gpt-4o-mini\",\"messages\":[{\"role\":\"user\",\"content\":${PROMPT_JSON}}]}" \
59
- --max-time 30 || echo "API_ERROR")
56
+ RESPONSE="API_ERROR"
57
+ for attempt in 1 2 3; do
58
+ RESULT=$(curl -s -X POST \
59
+ "https://models.github.ai/inference/chat/completions" \
60
+ -H "Authorization: Bearer ${GITHUB_TOKEN}" \
61
+ -H "Content-Type: application/json" \
62
+ -d "{\"model\":\"gpt-4o-mini\",\"messages\":[{\"role\":\"user\",\"content\":${PROMPT_JSON}}]}" \
63
+ -w "\n__HTTP_STATUS__:%{http_code}" \
64
+ --max-time 45 2>/dev/null)
65
+ HTTP_STATUS=$(echo "$RESULT" | grep -o '__HTTP_STATUS__:[0-9]*' | cut -d: -f2)
66
+ BODY=$(echo "$RESULT" | sed 's/__HTTP_STATUS__:[0-9]*$//')
67
+ echo "Attempt $attempt: HTTP $HTTP_STATUS"
68
+ if [ "$HTTP_STATUS" = "200" ]; then RESPONSE="$BODY"; break; fi
69
+ [ $attempt -lt 3 ] && sleep 20
70
+ done
60
71
 
61
72
  if [ "$RESPONSE" = "API_ERROR" ]; then
62
- gh pr edit "$PR_NUMBER" --add-label "infra:qa-broken"
73
+ GH_TOKEN="$PROJECT_TOKEN" gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" --method POST -f 'labels[]=infra:qa-broken'
63
74
  gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** Could not reach GitHub Models API. Manual review required."
64
- exit 0
75
+ exit 1
65
76
  fi
66
77
 
67
- VERDICT=$(echo "$RESPONSE" | python3 -c 'import json,sys,re; d=json.load(sys.stdin); t=d.get("choices",[{}])[0].get("message",{}).get("content","").strip(); first=t.split("\n")[0].upper() if t else ""; print("FAIL" if re.search(r"\bFAIL\b",first) else "PASS" if re.search(r"\bPASS\b",first) else "API_ERROR")')
78
+ VERDICT=$(echo "$RESPONSE" | python3 -c 'import json,sys,re; d=json.load(sys.stdin); t=d.get("choices",[{}])[0].get("message",{}).get("content","").strip(); lines=[l for l in t.split("\n") if not l.strip().startswith("```")]; first=lines[0].upper() if lines else ""; print("FAIL" if re.search(r"\bFAIL\b",first) else "PASS" if re.search(r"\bPASS\b",first) else "API_ERROR")')
68
79
  EXPLANATION=$(echo "$RESPONSE" | python3 -c 'import json,sys; d=json.load(sys.stdin); t=d.get("choices",[{}])[0].get("message",{}).get("content","").strip(); lines=t.split("\n",1); print(lines[1].strip() if len(lines)>1 else "")')
69
80
 
70
81
  if echo "$VERDICT" | grep -q "^PASS"; then
71
- gh pr edit "$PR_NUMBER" --add-label "qa:approved"
72
- gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** AC coverage verified. ${EXPLANATION}"
82
+ GH_TOKEN="$PROJECT_TOKEN" gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" --method POST -f 'labels[]=qa:approved'
83
+ gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** PASS
84
+
85
+ ${EXPLANATION}"
73
86
  elif echo "$VERDICT" | grep -q "^FAIL"; then
74
- gh pr edit "$PR_NUMBER" --add-label "qa:needs-work"
75
- gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** AC coverage insufficient. ${EXPLANATION}"
87
+ GH_TOKEN="$PROJECT_TOKEN" gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" --method POST -f 'labels[]=qa:needs-work'
88
+ gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** FAIL
89
+
90
+ ${EXPLANATION}"
76
91
  else
77
- gh pr edit "$PR_NUMBER" --add-label "infra:qa-broken"
92
+ GH_TOKEN="$PROJECT_TOKEN" gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" --method POST -f 'labels[]=infra:qa-broken'
78
93
  gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** Could not parse GitHub Models response. Manual review required."
94
+ exit 1
79
95
  fi
@@ -0,0 +1,51 @@
1
+ name: QA Gate
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize, reopened, labeled, unlabeled]
6
+
7
+ permissions:
8
+ pull-requests: read
9
+
10
+ jobs:
11
+ qa-gate:
12
+ name: QA Gate
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - name: Check QA status label
16
+ env:
17
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18
+ run: |
19
+ set -e
20
+ PR_NUMBER="${{ github.event.pull_request.number }}"
21
+ REPO="${{ github.repository }}"
22
+
23
+ PR_LABELS=$(gh pr view "$PR_NUMBER" --repo "$REPO" --json labels --jq '.labels[].name')
24
+
25
+ if echo "$PR_LABELS" | grep -qx "hotfix"; then
26
+ echo "✅ QA Gate: hotfix label — bypassed."
27
+ exit 0
28
+ fi
29
+
30
+ if echo "$PR_LABELS" | grep -qx "human-approved"; then
31
+ echo "✅ QA Gate: human-approved label — manual QA sign-off, bypassed."
32
+ exit 0
33
+ fi
34
+
35
+ if echo "$PR_LABELS" | grep -qx "qa:approved"; then
36
+ echo "✅ QA Gate: qa:approved — merge allowed."
37
+ exit 0
38
+ fi
39
+
40
+ if echo "$PR_LABELS" | grep -qx "infra:qa-broken"; then
41
+ echo "❌ QA Gate: infra:qa-broken — GitHub Models API unreachable. Manual QA review required before merge."
42
+ exit 1
43
+ fi
44
+
45
+ if echo "$PR_LABELS" | grep -qx "qa:needs-work"; then
46
+ echo "❌ QA Gate: qa:needs-work — acceptance criteria not fully met. Fix required before merge."
47
+ exit 1
48
+ fi
49
+
50
+ echo "❌ QA Gate: no QA label found — AC Coverage Verification has not completed. Wait for the check to finish."
51
+ exit 1
@@ -30,40 +30,87 @@ 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. **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 ACsdo 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.
33
+ 1. **Stage Check**: Before applying any label or taking any action, run `gh issue view <N> --json labels,title` to determine the issue's current stage. State: *"Issue #N [title] is currently at `<stage>`. Requesting confirmation to advance to `<next>`."* Wait for an explicit stage-advancement signal in this conversation turn. A prioritization signal ("work on X", "tackle X next") does **not** count as confirmation — only an explicit signal counts (e.g. "start brainstorming", "yes advance", "go"). **Exceptions — skip this step and proceed directly**:
34
+ - `spec:approved` begin implementation (gate already passed)
35
+ - `stage:development` or `stage:testing` issue is owned by automation; do not intervene unless explicitly asked to fix a specific problem
36
+ - `stage:approval` spec already written; wait for PM to add `spec:approved` before doing anything
37
+ 2. **Initial State**: Apply the `stage:brainstorming` label using the GitHub CLI (`gh issue edit <N> --add-label "stage:brainstorming"`). **Exception pre-spec'd issue**: if the issue body already contains all required spec sections (`## Problem`, `## Solution`, `## Acceptance Criteria`, `## Edge Cases`, `## Out of Scope`, `## Files to Modify`) all present and non-empty — apply `stage:approval` directly in a single call instead, skipping `stage:brainstorming` and `stage:detailing`.
38
+ 3. Read the issue entirely — understand its type (US/BUG/TASK/SPIKE) and the Acceptance Criteria.
39
+ 4. Read `docs/pdlc.md` understand the PDLC and the Definition of Done in this project.
40
+ 5. Read all files mentioned in the issue's technical context.
41
+ 6. Implement the **minimum viable change** that satisfies the ACs — do not refactor beyond scope.
42
+ 7. Run tests: `{{TEST_COMMAND}}`
43
+ 8. Run typecheck (if applicable): `{{TYPECHECK_COMMAND}}`
44
+ 9. Create a Pull Request with `Closes #N` in the body — automation moves the board.
41
45
 
42
- ### Spec format (Upstream Agents)
46
+ ## Spec Format
43
47
 
44
- When detailing a solution in an issue body, you must **always** include both the user story and the acceptance criteria. Never append only the ACs to an existing text; rewrite the full issue body in this standard format:
48
+ When writing or rewriting an issue body during detailing, include ALL sections below. Omitting any section blocks `stage:approval`.
49
+
50
+ **Destination: the issue body.** Write spec content to the issue body using `gh issue edit <N> --body "..."` — not to a file. A file is acceptable as optional reference only. Automation checks the issue body for `## Acceptance Criteria` and `## Files to Modify` to advance the stage; content that exists only in a file is invisible to it.
45
51
 
46
52
  ```
47
- **As** [user],
48
- **I want** [action],
49
- **so that** [benefit].
53
+ ## Problem
54
+ [1-3 sentences. What fails. Who affected. Measured impact.]
55
+
56
+ ## Sprint Goal / Success Metrics
57
+ | Metric | Baseline | Target | When |
58
+ |--------|----------|--------|------|
50
59
 
51
- ---
60
+ ## Solution
61
+ [Behavioral description of what is built. No implementation details.]
52
62
 
53
63
  ## Acceptance Criteria
64
+ **AC1 — [name]**
65
+ - Given [precondition]
66
+ - When [action]
67
+ - Then [outcome]
68
+
69
+ ## Edge Cases
70
+ - EC1: [condition] → [expected behavior]
54
71
 
55
- **AC1 ...**
56
- - Given ...
57
- - When ...
58
- - Then ...
72
+ ## Out of Scope
73
+ - [item] — reason
59
74
 
60
- **AC2 ...**
61
- ...
75
+ ## Non-Functional Requirements
76
+ - Performance: [metric with number]
77
+ - Security: [constraint]
78
+ - Reliability: [constraint]
79
+ > For pure docs/markdown issues with zero runtime behavior, include the NFRs section and state "N/A".
62
80
 
63
- ## Files to modify
64
- - `path/to/file.ts` — what changes
81
+ ## Files to Modify
82
+ - `path/to/file` — what changes
65
83
  ```
66
84
 
85
+ ## Stage Transition Rules (non-negotiable)
86
+
87
+ MUST apply `stage:brainstorming` label immediately on starting work — before reading
88
+ any code, before invoking any skill. Then read context and present problem summary
89
+ + 2–3 solution options in a single message.
90
+
91
+ MUST NOT add `stage:detailing` label until the user has explicitly selected
92
+ an approach in the current conversation turn. Work done in a prior
93
+ planning session does NOT count as confirmation.
94
+
95
+ MUST NOT add `spec:approved` or `stage:development` — these represent final
96
+ human approval or automation output. Adding them manually triggers irreversible
97
+ automation (Jules dispatch, board move).
98
+
99
+ MUST NOT manually add `stage:approval` except via the pre-spec'd exception
100
+ below. In the standard flow, `stage:approval` is set after you write a complete
101
+ spec and the user confirms; it is not applied before the spec exists.
102
+
103
+ Each stage transition requires a fresh explicit signal from the user in the same
104
+ session where the transition happens. The pre-spec'd exception is the only
105
+ deviation from this rule.
106
+
107
+ **Pre-spec'd exception**: if the issue body already contains all required spec
108
+ sections (`## Problem`, `## Solution`, `## Acceptance Criteria`, `## Edge Cases`,
109
+ `## Out of Scope`, `## Files to Modify`) — all present and non-empty — apply
110
+ `stage:approval` directly in a single `gh issue edit` call, skipping
111
+ `stage:brainstorming` and `stage:detailing`. One label event eliminates the
112
+ race condition that causes the project board to land on the wrong column.
113
+
67
114
  ## Pipeline Updates
68
115
 
69
116
  To add or configure optional agents (Jules, QA Agent, Sentinel) at any time:
@@ -80,7 +127,11 @@ Run this when the user says anything like "update the pipeline", "update the boa
80
127
  - Never open a PR without passing the tests.
81
128
  - Never implement beyond the immediate scope of the issue.
82
129
  - Never create future-proofing abstractions for hypothetical features.
83
- - Never add or remove `stage:*` or `qa:*` labels manually. These are owned by GitHub Actions automation and the PM only.
130
+ - The agent MUST NOT apply these labels under any circumstances (PM only):
131
+ - `spec:approved`: triggers Jules dispatch + board move to Development.
132
+ - `qa:approved`: triggers board move to Code Review.
133
+ - `qa:needs-work`: signals the PR requires changes and halts the flow.
134
+ - Never add or remove stage:* labels manually, except: `stage:brainstorming` as the initial label when starting work, or `stage:approval` directly when applying the pre-spec'd exception. All other stage transitions are owned by GitHub Actions automation and the PM.
84
135
  {{EXTRA_DONT}}
85
136
 
86
137
  ## Project Standards
@@ -4,9 +4,8 @@
4
4
 
5
5
  | Column | Meaning | Who moves the card |
6
6
  |---|---|---|
7
- | 💡 Idea — don't move manually to Exploration | Backlog — tell agent: "work on issue #XX" | Don't move manually |
8
- | 🔍 Exploration | Claude is analyzing code and context | Label `stage:exploration` |
9
- | 🧠 Brainstorming | Claude proposed approaches, awaiting PM gate | Label `stage:brainstorming` |
7
+ | 💡 Idea | Backlog — tell agent: "work on issue #XX" | Don't move manually |
8
+ | 🧠 Brainstorming | AI reading context, proposing approaches and trade-offs | Label `stage:brainstorming` |
10
9
  | 📐 Detail Solution | Claude is writing the technical spec | Label `stage:detailing` |
11
10
  | ✅ Approval | Spec ready, awaiting `spec:approved` label | Label `spec:approved` |
12
11
  | ⚙️ Development | Agent implementing the spec | Label `stage:development` |
@@ -37,7 +36,6 @@ REPO = {{REPO_OWNER}}/{{REPO_NAME}}
37
36
  | Column | Option ID |
38
37
  |---|---|
39
38
  | 💡 Idea | `{{ID_IDEA}}` |
40
- | 🔍 Exploration | `{{ID_EXPLORATION}}` |
41
39
  | 🧠 Brainstorming | `{{ID_BRAINSTORMING}}` |
42
40
  | 📐 Detail Solution | `{{ID_DETAIL}}` |
43
41
  | ✅ Approval | `{{ID_APPROVAL}}` |
@@ -60,7 +58,7 @@ REPO = {{REPO_OWNER}}/{{REPO_NAME}}
60
58
  ```
61
59
  [icon] [PREFIX]: [short description, imperative tense]
62
60
 
63
- 👤 US: user story
61
+ feat: new feature or behavioral change
64
62
  🐛 BUG: bug
65
63
  🔧 TASK: operational task
66
64
  🔬 SPIKE: exploration/evaluation spike
@@ -70,7 +68,6 @@ REPO = {{REPO_OWNER}}/{{REPO_NAME}}
70
68
 
71
69
  | Label | Entity | Color | Meaning |
72
70
  |---|---|---|---|
73
- | `stage:exploration` | Issue | Purple | Issue is being evaluated |
74
71
  | `stage:brainstorming` | Issue | Pink | Proposed approaches awaiting PM gate |
75
72
  | `stage:detailing` | Issue | Blue | Technical spec is being written |
76
73
  | `stage:development` | Issue | Orange | Agent is implementing the spec |
@@ -80,16 +77,16 @@ REPO = {{REPO_OWNER}}/{{REPO_NAME}}
80
77
  | `qa:approved` | PR | Green | QA Agent passed — AC coverage verified |
81
78
  | `qa:needs-work` | PR | Red | QA Agent failed — PR needs changes |
82
79
  | `infra:qa-broken` | PR | Orange | QA Agent error — manual review required |
83
- | `type:us` | Issue | Blue | New feature or behavioral change — full flow |
84
- | `type:task` | Issue | Yellow | Operational/non-functional change — skips brainstorming |
85
- | `type:bug` | Issue | Red | Something broken — skips brainstorming |
80
+ | `type:feature` | Issue | Blue | New feature or behavioral change — full flow |
81
+ | `type:task` | Issue | Yellow | Operational/non-functional change — full flow |
82
+ | `type:bug` | Issue | Red | Something broken — full flow |
86
83
  | `type:spike` | Issue | Gray | Research/evaluation — never reaches Development |
87
84
 
88
85
  ## Approval Gates
89
86
 
90
87
  **Gate 1 — PM/Ideation (Brainstorming):**
91
- You comment on the issue approving one of the approaches proposed by the ideation agent.
92
- Format: *"Approved — proceed with option X."*
88
+ Agent presents problem summary + 2–3 solution options in a single message. You select an approach.
89
+ Format: *"Option X"* or *"Go with B"* or *"Approved — proceed with option X."*
93
90
 
94
91
  **Gate 2 — Tech Lead (Spec):**
95
92
  You add the `spec:approved` label to the issue after reviewing the technical spec in the body.
@@ -101,12 +98,23 @@ The `type:*` label is the authoritative signal — set automatically by the agen
101
98
 
102
99
  | Label | Flow |
103
100
  |---|---|
104
- | `type:us` | Full flow — exploration → brainstorming → Gate 1 → detailing → approval |
105
- | `type:task` | Skips brainstorming exploration → detailing → approval |
106
- | `type:bug` | Skips brainstorming exploration → detailing → approval |
107
- | `type:spike` | Skips brainstorming exploration → detailing → conclusion comment (never reaches Development) |
101
+ | `type:feature` | brainstorming → Gate 1 → detailing → approval |
102
+ | `type:task` | brainstorming Gate 1 → detailing → approval |
103
+ | `type:bug` | brainstorming Gate 1 → detailing → approval |
104
+ | `type:spike` | brainstorming Gate 1 → detailing → conclusion comment (never reaches Development) |
108
105
 
109
- If no `type:*` label present and agent confidence < 85%, defaults to `type:us` (safe fallback — never skips gates by omission).
106
+ If no `type:*` label present and agent confidence < 85%, defaults to `type:feature` (safe fallback — never skips gates by omission).
107
+
108
+ ## Bypass Mechanism
109
+
110
+ Agents MUST NOT skip any stage. The ONLY authorized bypasses are:
111
+
112
+ | Mechanism | Who authorizes | What it bypasses |
113
+ |---|---|---|
114
+ | `human-approved` label on issue | PM (human) only | All stage gates |
115
+ | Branch prefix `hotfix/` | PM (human) only | PR gate only |
116
+
117
+ Agents MUST NOT self-authorize a bypass. Stop and ask the PM explicitly.
110
118
 
111
119
  ## Definition of Done
112
120
 
@@ -1,5 +0,0 @@
1
- # This file prevents autonomous agents from modifying core security, automation, and instruction rules
2
- # without explicit approval from the repository owner.
3
-
4
- .github/ @{{GITHUB_USERNAME}}
5
- AGENTS.md @{{GITHUB_USERNAME}}
@@ -1,12 +0,0 @@
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!