create-agentic-pdlc 2.2.1 → 2.3.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.
- package/.agentic-pdlc/SETUP_PROMPT.md +3 -4
- package/.agentic-pdlc/metrics/raw/2026-W18.jsonl +2 -0
- package/.agentic-pdlc/metrics/raw/2026-W21.jsonl +68 -0
- package/.agentic-pdlc/templates/.github/workflows/agent-trigger.yml +2 -2
- package/.agentic-pdlc/templates/.github/workflows/agentic-metrics.yml +16 -9
- package/.agentic-pdlc/templates/.github/workflows/ci.yml +14 -0
- package/.agentic-pdlc/templates/.github/workflows/pdlc-health-check.yml +0 -2
- package/.agentic-pdlc/templates/.github/workflows/project-automation.yml +1 -5
- package/.agentic-pdlc/templates/.github/workflows/qa-agent.yml +4 -4
- package/.agentic-pdlc/templates/AGENTS.md +24 -1
- package/.agentic-pdlc/templates/docs/pdlc.md +21 -13
- package/.agentic-setup-prompt.md +3 -4
- package/.agentic-setup.md +3 -4
- package/.github/workflows/agentic-metrics.yml +21 -11
- package/.github/workflows/pdlc-health-check.yml +0 -2
- package/.github/workflows/project-automation.yml +31 -7
- package/.github/workflows/qa-agent.yml +4 -4
- package/AGENTS.md +1 -1
- package/CLAUDE.md +51 -3
- package/SETUP.md +2 -0
- package/adapters/claude-code/skill.md +13 -10
- package/adapters/hooks/pdlc-stage-gate.sh +3 -3
- package/bin/cli.js +18 -7
- package/docs/flow.md +8 -21
- package/docs/pdlc.md +21 -13
- package/package.json +1 -1
- package/templates/.github/workflows/agent-trigger.yml +2 -2
- package/templates/.github/workflows/ci.yml +14 -0
- package/templates/.github/workflows/pdlc-health-check.yml +0 -2
- package/templates/.github/workflows/project-automation.yml +24 -6
- package/templates/.github/workflows/qa-agent.yml +6 -4
- package/templates/AGENTS.md +25 -2
- package/templates/docs/pdlc.md +21 -13
|
@@ -25,10 +25,10 @@ If any of these files are missing, you are in **Setup Mode**. Do not proceed wit
|
|
|
25
25
|
- **Project basics:** Project Name, Description, Technical Stack (Structure), and GitHub Username (for CODEOWNERS security).
|
|
26
26
|
- **Commands:** Test command, Lint command, Build command.
|
|
27
27
|
- **Invariants:** Critical business rules agents must never violate (e.g. Human-in-the-loop).
|
|
28
|
-
- **Board IDs:** PROJECT_ID, STATUS_FIELD_ID, column option IDs (provide standard PDLC options: Idea,
|
|
28
|
+
- **Board IDs:** PROJECT_ID, STATUS_FIELD_ID, column option IDs (provide standard PDLC options: Idea, Brainstorming, Detail Solution, Approval, Development, Testing, Code Review / PR, Production). Allow user to answer "skip", which means you leave the placeholders intact.
|
|
29
29
|
- **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.
|
|
30
30
|
- **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.
|
|
31
|
-
- **Implementation agent handle:** e.g., `@google-labs-jules`, or "none".
|
|
31
|
+
- **Implementation agent handle:** e.g., `@google-labs-jules`, or "none". When replacing `{{IMPLEMENTATION_AGENT_LABEL}}` in `agent-trigger.yml`: for Jules use `jules` (the native label the Jules GitHub App watches — **not** `agent:jules`); for other agents use the handle without `@`, lowercase.
|
|
32
32
|
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).
|
|
33
33
|
4. Offer to run the `gh` commands for labels (`spec:approved`, `pr:in-review`, `pr:approved`, `architecture-violation`).
|
|
34
34
|
5. Commit everything with the message: `chore: setup agentic-pdlc framework`.
|
|
@@ -68,6 +68,5 @@ Do not write code for downstream features! Your goal is to refine the Spec, so t
|
|
|
68
68
|
|
|
69
69
|
### 4. Moving the Board (Upstream States)
|
|
70
70
|
As you actively work with the user advancing the feature, you MUST use the GitHub CLI to update internal state labels. This triggers GitHub Actions behind the scenes.
|
|
71
|
-
- Starting
|
|
72
|
-
- Presenting architecture/approaches: Run `gh issue edit <N> --add-label "stage:brainstorming"`
|
|
71
|
+
- Starting work on an issue (before reading code): Run `gh issue edit <N> --add-label "stage:brainstorming"`
|
|
73
72
|
- Starting to write the technical spec: Run `gh issue edit <N> --add-label "stage:detailing"`
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{"issueNumber":66,"stage":"stage:development","durationDays":5}
|
|
2
|
+
{"issueNumber":66,"stage":"stage:approval","durationDays":0}
|
|
3
|
+
{"issueNumber":67,"stage":"stage:brainstorming","durationDays":0}
|
|
4
|
+
{"issueNumber":67,"stage":"stage:detailing","durationDays":0}
|
|
5
|
+
{"issueNumber":67,"stage":"stage:approval","durationDays":0}
|
|
6
|
+
{"issueNumber":74,"stage":"stage:detailing","durationDays":0}
|
|
7
|
+
{"issueNumber":74,"stage":"stage:approval","durationDays":0}
|
|
8
|
+
{"issueNumber":75,"stage":"stage:detailing","durationDays":0}
|
|
9
|
+
{"issueNumber":75,"stage":"stage:approval","durationDays":0}
|
|
10
|
+
{"issueNumber":76,"stage":"stage:detailing","durationDays":0}
|
|
11
|
+
{"issueNumber":76,"stage":"stage:approval","durationDays":0}
|
|
12
|
+
{"issueNumber":78,"stage":"stage:detailing","durationDays":0}
|
|
13
|
+
{"issueNumber":78,"stage":"stage:approval","durationDays":0}
|
|
14
|
+
{"issueNumber":80,"stage":"stage:detailing","durationDays":0}
|
|
15
|
+
{"issueNumber":80,"stage":"stage:approval","durationDays":0}
|
|
16
|
+
{"issueNumber":80,"stage":"stage:development","durationDays":3.1}
|
|
17
|
+
{"issueNumber":84,"stage":"stage:brainstorming","durationDays":0}
|
|
18
|
+
{"issueNumber":84,"stage":"stage:detailing","durationDays":0}
|
|
19
|
+
{"issueNumber":84,"stage":"stage:approval","durationDays":0}
|
|
20
|
+
{"issueNumber":84,"stage":"stage:development","durationDays":0}
|
|
21
|
+
{"issueNumber":85,"stage":"stage:brainstorming","durationDays":0}
|
|
22
|
+
{"issueNumber":85,"stage":"stage:detailing","durationDays":0}
|
|
23
|
+
{"issueNumber":85,"stage":"stage:approval","durationDays":0}
|
|
24
|
+
{"issueNumber":85,"stage":"stage:approval","durationDays":0}
|
|
25
|
+
{"issueNumber":87,"stage":"stage:approval","durationDays":0}
|
|
26
|
+
{"issueNumber":87,"stage":"stage:development","durationDays":0}
|
|
27
|
+
{"issueNumber":87,"stage":"stage:brainstorming","durationDays":0}
|
|
28
|
+
{"issueNumber":87,"stage":"stage:detailing","durationDays":0}
|
|
29
|
+
{"issueNumber":87,"stage":"stage:approval","durationDays":0}
|
|
30
|
+
{"issueNumber":88,"stage":"stage:brainstorming","durationDays":0}
|
|
31
|
+
{"issueNumber":88,"stage":"stage:detailing","durationDays":0}
|
|
32
|
+
{"issueNumber":88,"stage":"stage:approval","durationDays":0}
|
|
33
|
+
{"issueNumber":88,"stage":"stage:development","durationDays":0}
|
|
34
|
+
{"issueNumber":89,"stage":"stage:brainstorming","durationDays":0}
|
|
35
|
+
{"issueNumber":90,"stage":"stage:brainstorming","durationDays":0}
|
|
36
|
+
{"issueNumber":90,"stage":"stage:detailing","durationDays":0}
|
|
37
|
+
{"issueNumber":90,"stage":"stage:approval","durationDays":0}
|
|
38
|
+
{"issueNumber":90,"stage":"stage:approval","durationDays":0}
|
|
39
|
+
{"issueNumber":91,"stage":"stage:brainstorming","durationDays":0}
|
|
40
|
+
{"issueNumber":91,"stage":"stage:detailing","durationDays":0}
|
|
41
|
+
{"issueNumber":91,"stage":"stage:approval","durationDays":0}
|
|
42
|
+
{"issueNumber":91,"stage":"stage:development","durationDays":0}
|
|
43
|
+
{"issueNumber":92,"stage":"stage:brainstorming","durationDays":0}
|
|
44
|
+
{"issueNumber":92,"stage":"stage:detailing","durationDays":0}
|
|
45
|
+
{"issueNumber":92,"stage":"stage:approval","durationDays":0}
|
|
46
|
+
{"issueNumber":92,"stage":"stage:development","durationDays":0}
|
|
47
|
+
{"issueNumber":93,"stage":"stage:brainstorming","durationDays":0}
|
|
48
|
+
{"issueNumber":93,"stage":"stage:detailing","durationDays":0}
|
|
49
|
+
{"issueNumber":93,"stage":"stage:approval","durationDays":0}
|
|
50
|
+
{"issueNumber":93,"stage":"stage:development","durationDays":0}
|
|
51
|
+
{"issueNumber":94,"stage":"stage:brainstorming","durationDays":0}
|
|
52
|
+
{"issueNumber":94,"stage":"stage:detailing","durationDays":0}
|
|
53
|
+
{"issueNumber":94,"stage":"stage:approval","durationDays":0}
|
|
54
|
+
{"issueNumber":96,"stage":"stage:brainstorming","durationDays":0}
|
|
55
|
+
{"issueNumber":96,"stage":"stage:detailing","durationDays":0}
|
|
56
|
+
{"issueNumber":96,"stage":"stage:approval","durationDays":0}
|
|
57
|
+
{"issueNumber":96,"stage":"stage:development","durationDays":0}
|
|
58
|
+
{"issueNumber":97,"stage":"stage:brainstorming","durationDays":0}
|
|
59
|
+
{"issueNumber":97,"stage":"stage:detailing","durationDays":0}
|
|
60
|
+
{"issueNumber":97,"stage":"stage:approval","durationDays":0}
|
|
61
|
+
{"issueNumber":109,"stage":"stage:brainstorming","durationDays":0}
|
|
62
|
+
{"issueNumber":109,"stage":"stage:detailing","durationDays":0}
|
|
63
|
+
{"issueNumber":109,"stage":"stage:approval","durationDays":0}
|
|
64
|
+
{"issueNumber":109,"stage":"stage:development","durationDays":0}
|
|
65
|
+
{"issueNumber":113,"stage":"stage:brainstorming","durationDays":0}
|
|
66
|
+
{"issueNumber":113,"stage":"stage:detailing","durationDays":0}
|
|
67
|
+
{"issueNumber":113,"stage":"stage:approval","durationDays":0}
|
|
68
|
+
{"issueNumber":113,"stage":"stage:development","durationDays":0}
|
|
@@ -75,7 +75,7 @@ jobs:
|
|
|
75
75
|
console.log(`Issue #${number} → Development`);
|
|
76
76
|
|
|
77
77
|
- name: Comment on issue to trigger agent and prevent race conditions
|
|
78
|
-
if: ${{ !contains('{{IMPLEMENTATION_AGENT_LABEL}}', '{{') }}
|
|
78
|
+
if: ${{ !contains('{{IMPLEMENTATION_AGENT_LABEL}}', '{{') && vars.JULES_ENABLED == 'true' }}
|
|
79
79
|
uses: actions/github-script@v7
|
|
80
80
|
with:
|
|
81
81
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -118,7 +118,7 @@ jobs:
|
|
|
118
118
|
contents: read
|
|
119
119
|
steps:
|
|
120
120
|
- name: Comment on issue to trigger agent
|
|
121
|
-
if: ${{ !contains('{{IMPLEMENTATION_AGENT_LABEL}}', '{{') }}
|
|
121
|
+
if: ${{ !contains('{{IMPLEMENTATION_AGENT_LABEL}}', '{{') && vars.JULES_ENABLED == 'true' }}
|
|
122
122
|
uses: actions/github-script@v7
|
|
123
123
|
with:
|
|
124
124
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -25,7 +25,7 @@ jobs:
|
|
|
25
25
|
const { owner, repo } = context.repo;
|
|
26
26
|
const since = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
|
|
27
27
|
const STAGE_LABELS = new Set([
|
|
28
|
-
'stage:
|
|
28
|
+
'stage:brainstorming', 'stage:detailing',
|
|
29
29
|
'stage:approval', 'stage:development', 'stage:testing'
|
|
30
30
|
]);
|
|
31
31
|
|
|
@@ -297,7 +297,6 @@ jobs:
|
|
|
297
297
|
const records = fs.readFileSync(jsonlPath, 'utf8').trim().split('\n').filter(Boolean).map(JSON.parse);
|
|
298
298
|
if (records.length > 0) {
|
|
299
299
|
const STAGES = [
|
|
300
|
-
['stage:exploration', 'Exploration'],
|
|
301
300
|
['stage:brainstorming', 'Brainstorming'],
|
|
302
301
|
['stage:detailing', 'Detailing'],
|
|
303
302
|
['stage:approval', 'Approval'],
|
|
@@ -394,19 +393,27 @@ jobs:
|
|
|
394
393
|
console.log(`Created label ${LABEL}`);
|
|
395
394
|
}
|
|
396
395
|
|
|
397
|
-
// Close previous pulse issues
|
|
396
|
+
// Close previous pulse issues; upsert if same week already exists
|
|
398
397
|
const prev = await github.rest.issues.listForRepo({
|
|
399
398
|
owner, repo, labels: LABEL, state: 'open', per_page: 20
|
|
400
399
|
});
|
|
400
|
+
let existingIssue = null;
|
|
401
401
|
for (const issue of prev.data) {
|
|
402
|
-
if (issue.title
|
|
402
|
+
if (issue.title === title) {
|
|
403
|
+
existingIssue = issue;
|
|
404
|
+
console.log(`Found existing pulse for ${title}: #${issue.number} — will update body`);
|
|
405
|
+
} else {
|
|
403
406
|
await github.rest.issues.update({ owner, repo, issue_number: issue.number, state: 'closed' });
|
|
404
407
|
console.log(`Closed previous pulse: #${issue.number}`);
|
|
405
408
|
}
|
|
406
409
|
}
|
|
407
410
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
}
|
|
412
|
-
|
|
411
|
+
if (existingIssue) {
|
|
412
|
+
await github.rest.issues.update({ owner, repo, issue_number: existingIssue.number, body });
|
|
413
|
+
console.log(`✅ Updated pulse issue: #${existingIssue.number} — ${title}`);
|
|
414
|
+
} else {
|
|
415
|
+
const created = await github.rest.issues.create({
|
|
416
|
+
owner, repo, title, body, labels: [LABEL]
|
|
417
|
+
});
|
|
418
|
+
console.log(`✅ Created pulse issue: #${created.data.number} — ${title}`);
|
|
419
|
+
}
|
|
@@ -38,3 +38,17 @@ jobs:
|
|
|
38
38
|
if: ${{ !contains('{{TEST_COMMAND}}', '{{') }}
|
|
39
39
|
run: |
|
|
40
40
|
{{TEST_COMMAND}}
|
|
41
|
+
|
|
42
|
+
ci-status:
|
|
43
|
+
name: Sentinel / CI
|
|
44
|
+
needs: [validate]
|
|
45
|
+
if: always()
|
|
46
|
+
runs-on: ubuntu-latest
|
|
47
|
+
steps:
|
|
48
|
+
- name: Check validate result
|
|
49
|
+
run: |
|
|
50
|
+
result="${{ needs.validate.result }}"
|
|
51
|
+
if [[ "$result" != "success" && "$result" != "skipped" ]]; then
|
|
52
|
+
echo "CI failed: validate=$result"
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
@@ -8,7 +8,6 @@ on:
|
|
|
8
8
|
env:
|
|
9
9
|
PROJECT_ID: "{{PROJECT_ID}}"
|
|
10
10
|
STATUS_FIELD_ID: "{{STATUS_FIELD_ID}}"
|
|
11
|
-
STATUS_EXPLORATION: "{{ID_EXPLORATION}}"
|
|
12
11
|
STATUS_BRAINSTORMING: "{{ID_BRAINSTORMING}}"
|
|
13
12
|
STATUS_DETAILING: "{{ID_DETAILING}}"
|
|
14
13
|
STATUS_APPROVAL: "{{ID_APPROVAL}}"
|
|
@@ -35,7 +34,6 @@ jobs:
|
|
|
35
34
|
const projectId = process.env.PROJECT_ID;
|
|
36
35
|
const statusFieldId = process.env.STATUS_FIELD_ID;
|
|
37
36
|
const envVars = {
|
|
38
|
-
'STATUS_EXPLORATION': process.env.STATUS_EXPLORATION,
|
|
39
37
|
'STATUS_BRAINSTORMING': process.env.STATUS_BRAINSTORMING,
|
|
40
38
|
'STATUS_DETAILING': process.env.STATUS_DETAILING,
|
|
41
39
|
'STATUS_APPROVAL': process.env.STATUS_APPROVAL,
|
|
@@ -12,7 +12,6 @@ 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}}"
|
|
@@ -40,10 +39,7 @@ jobs:
|
|
|
40
39
|
let targetStatusId = null;
|
|
41
40
|
let stageName = null;
|
|
42
41
|
|
|
43
|
-
if (labelName === 'stage:
|
|
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') {
|
|
@@ -64,7 +64,7 @@ jobs:
|
|
|
64
64
|
--max-time 30 || echo "API_ERROR")
|
|
65
65
|
|
|
66
66
|
if [ "$RESPONSE" = "API_ERROR" ]; then
|
|
67
|
-
gh
|
|
67
|
+
GH_TOKEN="$PROJECT_PAT" gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" --method POST -f 'labels[]=infra:qa-broken'
|
|
68
68
|
gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** Could not reach GitHub Models API. Manual review required."
|
|
69
69
|
exit 0
|
|
70
70
|
fi
|
|
@@ -73,13 +73,13 @@ jobs:
|
|
|
73
73
|
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 "")')
|
|
74
74
|
|
|
75
75
|
if echo "$VERDICT" | grep -q "^PASS"; then
|
|
76
|
-
gh
|
|
76
|
+
GH_TOKEN="$PROJECT_PAT" gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" --method POST -f 'labels[]=qa:approved'
|
|
77
77
|
gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** AC coverage verified. ${EXPLANATION}"
|
|
78
78
|
elif echo "$VERDICT" | grep -q "^FAIL"; then
|
|
79
|
-
gh
|
|
79
|
+
GH_TOKEN="$PROJECT_PAT" gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" --method POST -f 'labels[]=qa:needs-work'
|
|
80
80
|
gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** AC coverage insufficient. ${EXPLANATION}"
|
|
81
81
|
else
|
|
82
|
-
gh
|
|
82
|
+
GH_TOKEN="$PROJECT_PAT" gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" --method POST -f 'labels[]=infra:qa-broken'
|
|
83
83
|
gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** Could not parse GitHub Models response. Manual review required."
|
|
84
84
|
fi
|
|
85
85
|
|
|
@@ -30,7 +30,7 @@ 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:
|
|
33
|
+
1. **Initial State**: When beginning work on a new issue, your very first action must be to apply the `stage:brainstorming` label using the GitHub CLI (`gh issue edit <N> --add-label "stage:brainstorming"`).
|
|
34
34
|
2. Read the issue entirely — understand its type (US/BUG/TASK/SPIKE) and the Acceptance Criteria.
|
|
35
35
|
3. Read `docs/pdlc.md` — understand the PDLC and the Definition of Done in this project.
|
|
36
36
|
4. Read all files mentioned in the issue's technical context.
|
|
@@ -64,12 +64,35 @@ When detailing a solution in an issue body, you must **always** include both the
|
|
|
64
64
|
- `path/to/file.ts` — what changes
|
|
65
65
|
```
|
|
66
66
|
|
|
67
|
+
## Stage Transition Rules (non-negotiable)
|
|
68
|
+
|
|
69
|
+
MUST apply `stage:brainstorming` label immediately on starting work — before reading
|
|
70
|
+
any code, before invoking any skill. Then read context and present problem summary
|
|
71
|
+
+ 2–3 solution options in a single message.
|
|
72
|
+
|
|
73
|
+
MUST NOT add `stage:detailing` label until the user has explicitly selected
|
|
74
|
+
an approach in the current conversation turn. Work done in a prior
|
|
75
|
+
planning session does NOT count as confirmation.
|
|
76
|
+
|
|
77
|
+
MUST NOT add `spec:approved`, `stage:development`, or manually add
|
|
78
|
+
`stage:approval` — these represent final human approval or the result of it.
|
|
79
|
+
`stage:approval` is only set by system automation after you provide a complete
|
|
80
|
+
spec for human review. Adding them manually triggers irreversible automation
|
|
81
|
+
(Jules dispatch, board move).
|
|
82
|
+
|
|
83
|
+
Each stage transition requires a fresh explicit signal from the user in the same
|
|
84
|
+
session where the transition happens. These rules have no exceptions.
|
|
85
|
+
|
|
67
86
|
## What NOT to do
|
|
68
87
|
|
|
69
88
|
- Never commit directly to `main`.
|
|
70
89
|
- Never open a PR without passing the tests.
|
|
71
90
|
- Never implement beyond the immediate scope of the issue.
|
|
72
91
|
- Never create future-proofing abstractions for hypothetical features.
|
|
92
|
+
- The agent MUST NOT apply these labels under any circumstances (PM only):
|
|
93
|
+
- `spec:approved`: triggers Jules dispatch + board move to Development.
|
|
94
|
+
- `qa:approved`: triggers board move to Code Review.
|
|
95
|
+
- `qa:needs-work`: signals the PR requires changes and halts the flow.
|
|
73
96
|
{{EXTRA_DONT}}
|
|
74
97
|
|
|
75
98
|
## Project Standards
|
|
@@ -4,9 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
| Column | Meaning | Who moves the card |
|
|
6
6
|
|---|---|---|
|
|
7
|
-
| 💡 Idea
|
|
8
|
-
|
|
|
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}}` |
|
|
@@ -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 |
|
|
@@ -78,15 +75,15 @@ REPO = {{REPO_OWNER}}/{{REPO_NAME}}
|
|
|
78
75
|
| `pr:in-review` | PR | Yellow | Awaiting code review |
|
|
79
76
|
| `pr:approved` | PR | Green | Code review approved |
|
|
80
77
|
| `type:us` | Issue | Blue | New feature or behavioral change — full flow |
|
|
81
|
-
| `type:task` | Issue | Yellow | Operational/non-functional change —
|
|
82
|
-
| `type:bug` | Issue | Red | Something broken —
|
|
78
|
+
| `type:task` | Issue | Yellow | Operational/non-functional change — full flow |
|
|
79
|
+
| `type:bug` | Issue | Red | Something broken — full flow |
|
|
83
80
|
| `type:spike` | Issue | Gray | Research/evaluation — never reaches Development |
|
|
84
81
|
|
|
85
82
|
## Approval Gates
|
|
86
83
|
|
|
87
84
|
**Gate 1 — PM/Ideation (Brainstorming):**
|
|
88
|
-
|
|
89
|
-
Format: *"Approved — proceed with option X."*
|
|
85
|
+
Agent presents problem summary + 2–3 solution options in a single message. You select an approach.
|
|
86
|
+
Format: *"Option X"* or *"Go with B"* or *"Approved — proceed with option X."*
|
|
90
87
|
|
|
91
88
|
**Gate 2 — Tech Lead (Spec):**
|
|
92
89
|
You add the `spec:approved` label to the issue after reviewing the technical spec in the body.
|
|
@@ -98,13 +95,24 @@ The `type:*` label is the authoritative signal — set automatically by the agen
|
|
|
98
95
|
|
|
99
96
|
| Label | Flow |
|
|
100
97
|
|---|---|
|
|
101
|
-
| `type:us` |
|
|
102
|
-
| `type:task` |
|
|
103
|
-
| `type:bug` |
|
|
104
|
-
| `type:spike` |
|
|
98
|
+
| `type:us` | brainstorming → Gate 1 → detailing → approval |
|
|
99
|
+
| `type:task` | brainstorming → Gate 1 → detailing → approval |
|
|
100
|
+
| `type:bug` | brainstorming → Gate 1 → detailing → approval |
|
|
101
|
+
| `type:spike` | brainstorming → Gate 1 → detailing → conclusion comment (never reaches Development) |
|
|
105
102
|
|
|
106
103
|
If no `type:*` label present and agent confidence < 85%, defaults to `type:us` (safe fallback — never skips gates by omission).
|
|
107
104
|
|
|
105
|
+
## Bypass Mechanism
|
|
106
|
+
|
|
107
|
+
Agents MUST NOT skip any stage. The ONLY authorized bypasses are:
|
|
108
|
+
|
|
109
|
+
| Mechanism | Who authorizes | What it bypasses |
|
|
110
|
+
|---|---|---|
|
|
111
|
+
| `human-approved` label on issue | PM (human) only | All stage gates |
|
|
112
|
+
| Branch prefix `hotfix/` | PM (human) only | PR gate only |
|
|
113
|
+
|
|
114
|
+
Agents MUST NOT self-authorize a bypass. Stop and ask the PM explicitly.
|
|
115
|
+
|
|
108
116
|
## Definition of Done
|
|
109
117
|
|
|
110
118
|
An issue is truly done when:
|
package/.agentic-setup-prompt.md
CHANGED
|
@@ -25,10 +25,10 @@ If any of these files are missing, you are in **Setup Mode**. Do not proceed wit
|
|
|
25
25
|
- **Project basics:** Project Name, Description, Technical Stack (Structure), and GitHub Username (for CODEOWNERS security).
|
|
26
26
|
- **Commands:** Test command, Lint command, Build command.
|
|
27
27
|
- **Invariants:** Critical business rules agents must never violate (e.g. Human-in-the-loop).
|
|
28
|
-
- **Board IDs:** PROJECT_ID, STATUS_FIELD_ID, column option IDs (provide standard PDLC options: Idea,
|
|
28
|
+
- **Board IDs:** PROJECT_ID, STATUS_FIELD_ID, column option IDs (provide standard PDLC options: Idea, Brainstorming, Detail Solution, Approval, Development, Testing, Code Review / PR, Production). Allow user to answer "skip", which means you leave the placeholders intact.
|
|
29
29
|
- **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.
|
|
30
30
|
- **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.
|
|
31
|
-
- **Implementation agent handle:** e.g., `@google-labs-jules`, or "none".
|
|
31
|
+
- **Implementation agent handle:** e.g., `@google-labs-jules`, or "none". When replacing `{{IMPLEMENTATION_AGENT_LABEL}}` in `agent-trigger.yml`: for Jules use `jules` (the native label the Jules GitHub App watches — **not** `agent:jules`); for other agents use the handle without `@`, lowercase.
|
|
32
32
|
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).
|
|
33
33
|
4. Offer to run the `gh` commands for labels (`spec:approved`, `pr:in-review`, `pr:approved`, `architecture-violation`).
|
|
34
34
|
5. Commit everything with the message: `chore: setup agentic-pdlc framework`.
|
|
@@ -68,6 +68,5 @@ Do not write code for downstream features! Your goal is to refine the Spec, so t
|
|
|
68
68
|
|
|
69
69
|
### 4. Moving the Board (Upstream States)
|
|
70
70
|
As you actively work with the user advancing the feature, you MUST use the GitHub CLI to update internal state labels. This triggers GitHub Actions behind the scenes.
|
|
71
|
-
- Starting
|
|
72
|
-
- Presenting architecture/approaches: Run `gh issue edit <N> --add-label "stage:brainstorming"`
|
|
71
|
+
- Starting work on an issue (before reading code): Run `gh issue edit <N> --add-label "stage:brainstorming"`
|
|
73
72
|
- Starting to write the technical spec: Run `gh issue edit <N> --add-label "stage:detailing"`
|
package/.agentic-setup.md
CHANGED
|
@@ -25,10 +25,10 @@ If any of these files are missing, you are in **Setup Mode**. Do not proceed wit
|
|
|
25
25
|
- **Project basics:** Project Name, Description, Technical Stack (Structure), and GitHub Username (for CODEOWNERS security).
|
|
26
26
|
- **Commands:** Test command, Lint command, Build command.
|
|
27
27
|
- **Invariants:** Critical business rules agents must never violate (e.g. Human-in-the-loop).
|
|
28
|
-
- **Board IDs:** PROJECT_ID, STATUS_FIELD_ID, column option IDs (provide standard PDLC options: Idea,
|
|
28
|
+
- **Board IDs:** PROJECT_ID, STATUS_FIELD_ID, column option IDs (provide standard PDLC options: Idea, Brainstorming, Detail Solution, Approval, Development, Testing, Code Review / PR, Production). Allow user to answer "skip", which means you leave the placeholders intact.
|
|
29
29
|
- **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.
|
|
30
30
|
- **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.
|
|
31
|
-
- **Implementation agent handle:** e.g., `@google-labs-jules`, or "none".
|
|
31
|
+
- **Implementation agent handle:** e.g., `@google-labs-jules`, or "none". When replacing `{{IMPLEMENTATION_AGENT_LABEL}}` in `agent-trigger.yml`: for Jules use `jules` (the native label the Jules GitHub App watches — **not** `agent:jules`); for other agents use the handle without `@`, lowercase.
|
|
32
32
|
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).
|
|
33
33
|
4. Offer to run the `gh` commands for labels (`spec:approved`, `pr:in-review`, `pr:approved`, `architecture-violation`).
|
|
34
34
|
5. Commit everything with the message: `chore: setup agentic-pdlc framework`.
|
|
@@ -68,6 +68,5 @@ Do not write code for downstream features! Your goal is to refine the Spec, so t
|
|
|
68
68
|
|
|
69
69
|
### 4. Moving the Board (Upstream States)
|
|
70
70
|
As you actively work with the user advancing the feature, you MUST use the GitHub CLI to update internal state labels. This triggers GitHub Actions behind the scenes.
|
|
71
|
-
- Starting
|
|
72
|
-
- Presenting architecture/approaches: Run `gh issue edit <N> --add-label "stage:brainstorming"`
|
|
71
|
+
- Starting work on an issue (before reading code): Run `gh issue edit <N> --add-label "stage:brainstorming"`
|
|
73
72
|
- Starting to write the technical spec: Run `gh issue edit <N> --add-label "stage:detailing"`
|
|
@@ -25,7 +25,7 @@ jobs:
|
|
|
25
25
|
const { owner, repo } = context.repo;
|
|
26
26
|
const since = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
|
|
27
27
|
const STAGE_LABELS = new Set([
|
|
28
|
-
'stage:
|
|
28
|
+
'stage:brainstorming', 'stage:detailing',
|
|
29
29
|
'stage:approval', 'stage:development', 'stage:testing'
|
|
30
30
|
]);
|
|
31
31
|
|
|
@@ -297,7 +297,6 @@ jobs:
|
|
|
297
297
|
const records = fs.readFileSync(jsonlPath, 'utf8').trim().split('\n').filter(Boolean).map(JSON.parse);
|
|
298
298
|
if (records.length > 0) {
|
|
299
299
|
const STAGES = [
|
|
300
|
-
['stage:exploration', 'Exploration'],
|
|
301
300
|
['stage:brainstorming', 'Brainstorming'],
|
|
302
301
|
['stage:detailing', 'Detailing'],
|
|
303
302
|
['stage:approval', 'Approval'],
|
|
@@ -311,11 +310,14 @@ jobs:
|
|
|
311
310
|
}
|
|
312
311
|
const avg = arr => arr.reduce((a, b) => a + b, 0) / arr.length;
|
|
313
312
|
|
|
314
|
-
let maxStage = null, maxDays =
|
|
313
|
+
let maxStage = null, maxDays = -1;
|
|
315
314
|
const rows = [];
|
|
316
315
|
for (const [stage, label] of STAGES) {
|
|
317
316
|
const days = byStage[stage];
|
|
318
|
-
if (!days)
|
|
317
|
+
if (!days) {
|
|
318
|
+
rows.push(`| **${label}** | — | — |`);
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
319
321
|
const a = round1(avg(days));
|
|
320
322
|
rows.push(`| **${label}** | ${a}d | ${days.length} |`);
|
|
321
323
|
if (a > maxDays) { maxStage = label; maxDays = a; }
|
|
@@ -394,19 +396,27 @@ jobs:
|
|
|
394
396
|
console.log(`Created label ${LABEL}`);
|
|
395
397
|
}
|
|
396
398
|
|
|
397
|
-
// Close previous pulse issues
|
|
399
|
+
// Close previous pulse issues; upsert if same week already exists
|
|
398
400
|
const prev = await github.rest.issues.listForRepo({
|
|
399
401
|
owner, repo, labels: LABEL, state: 'open', per_page: 20
|
|
400
402
|
});
|
|
403
|
+
let existingIssue = null;
|
|
401
404
|
for (const issue of prev.data) {
|
|
402
|
-
if (issue.title
|
|
405
|
+
if (issue.title === title) {
|
|
406
|
+
existingIssue = issue;
|
|
407
|
+
console.log(`Found existing pulse for ${title}: #${issue.number} — will update body`);
|
|
408
|
+
} else {
|
|
403
409
|
await github.rest.issues.update({ owner, repo, issue_number: issue.number, state: 'closed' });
|
|
404
410
|
console.log(`Closed previous pulse: #${issue.number}`);
|
|
405
411
|
}
|
|
406
412
|
}
|
|
407
413
|
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
}
|
|
412
|
-
|
|
414
|
+
if (existingIssue) {
|
|
415
|
+
await github.rest.issues.update({ owner, repo, issue_number: existingIssue.number, body });
|
|
416
|
+
console.log(`✅ Updated pulse issue: #${existingIssue.number} — ${title}`);
|
|
417
|
+
} else {
|
|
418
|
+
const created = await github.rest.issues.create({
|
|
419
|
+
owner, repo, title, body, labels: [LABEL]
|
|
420
|
+
});
|
|
421
|
+
console.log(`✅ Created pulse issue: #${created.data.number} — ${title}`);
|
|
422
|
+
}
|
|
@@ -8,7 +8,6 @@ on:
|
|
|
8
8
|
env:
|
|
9
9
|
PROJECT_ID: "PVT_kwHODpFFL84BXg7h"
|
|
10
10
|
STATUS_FIELD_ID: "PVTSSF_lAHODpFFL84BXg7hzhStRHI"
|
|
11
|
-
STATUS_EXPLORATION: "96ac537d"
|
|
12
11
|
STATUS_BRAINSTORMING: "8eb07c5b"
|
|
13
12
|
STATUS_DETAILING: "9f6ce70e"
|
|
14
13
|
STATUS_APPROVAL: "31bf4610"
|
|
@@ -35,7 +34,6 @@ jobs:
|
|
|
35
34
|
const projectId = process.env.PROJECT_ID;
|
|
36
35
|
const statusFieldId = process.env.STATUS_FIELD_ID;
|
|
37
36
|
const envVars = {
|
|
38
|
-
'STATUS_EXPLORATION': process.env.STATUS_EXPLORATION,
|
|
39
37
|
'STATUS_BRAINSTORMING': process.env.STATUS_BRAINSTORMING,
|
|
40
38
|
'STATUS_DETAILING': process.env.STATUS_DETAILING,
|
|
41
39
|
'STATUS_APPROVAL': process.env.STATUS_APPROVAL,
|
|
@@ -6,13 +6,12 @@ on:
|
|
|
6
6
|
pull_request_review:
|
|
7
7
|
types: [submitted]
|
|
8
8
|
issues:
|
|
9
|
-
types: [labeled]
|
|
9
|
+
types: [labeled, closed]
|
|
10
10
|
|
|
11
11
|
env:
|
|
12
12
|
PROJECT_ID: "PVT_kwHODpFFL84BXg7h"
|
|
13
13
|
STATUS_FIELD_ID: "PVTSSF_lAHODpFFL84BXg7hzhStRHI"
|
|
14
14
|
STATUS_IDEA: "bb6e5a20"
|
|
15
|
-
STATUS_EXPLORATION: "96ac537d"
|
|
16
15
|
STATUS_BRAINSTORMING: "8eb07c5b"
|
|
17
16
|
STATUS_DETAILING: "9f6ce70e"
|
|
18
17
|
STATUS_APPROVAL: "31bf4610"
|
|
@@ -40,10 +39,7 @@ jobs:
|
|
|
40
39
|
let targetStatusId = null;
|
|
41
40
|
let stageName = null;
|
|
42
41
|
|
|
43
|
-
if (labelName === 'stage:
|
|
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') {
|
|
@@ -156,11 +152,17 @@ jobs:
|
|
|
156
152
|
});
|
|
157
153
|
};
|
|
158
154
|
|
|
155
|
+
const stageLabelsToRemove = ['stage:development', 'stage:brainstorming', 'stage:detailing', 'stage:approval', 'jules', 'agent:working'];
|
|
156
|
+
|
|
159
157
|
if (linkedIssues.length > 0) {
|
|
160
158
|
for (const n of linkedIssues) {
|
|
161
159
|
const { data: issue } = await github.rest.issues.get({ owner, repo, issue_number: n });
|
|
162
160
|
await moveItem(issue.node_id);
|
|
163
|
-
|
|
161
|
+
for (const label of stageLabelsToRemove) {
|
|
162
|
+
await github.rest.issues.removeLabel({ owner, repo, issue_number: n, name: label }).catch(() => {});
|
|
163
|
+
}
|
|
164
|
+
await github.rest.issues.addLabels({ owner, repo, issue_number: n, labels: ['stage:testing'] }).catch(() => {});
|
|
165
|
+
console.log(`Issue #${n} → Testing (labels updated)`);
|
|
164
166
|
}
|
|
165
167
|
} else {
|
|
166
168
|
await moveItem(pr.node_id);
|
|
@@ -282,3 +284,25 @@ jobs:
|
|
|
282
284
|
} else {
|
|
283
285
|
await moveItem(pr.node_id);
|
|
284
286
|
}
|
|
287
|
+
|
|
288
|
+
cleanup-labels-on-close:
|
|
289
|
+
name: Issue closed → strip stage/agent labels
|
|
290
|
+
if: github.event_name == 'issues' && github.event.action == 'closed'
|
|
291
|
+
runs-on: ubuntu-latest
|
|
292
|
+
steps:
|
|
293
|
+
- name: Remove transient labels
|
|
294
|
+
uses: actions/github-script@v7
|
|
295
|
+
with:
|
|
296
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
297
|
+
script: |
|
|
298
|
+
const { owner, repo } = context.repo;
|
|
299
|
+
const issue_number = context.payload.issue.number;
|
|
300
|
+
const toRemove = [
|
|
301
|
+
'stage:brainstorming', 'stage:detailing',
|
|
302
|
+
'stage:approval', 'stage:development', 'stage:testing',
|
|
303
|
+
'agent:working', 'qa:needs-work', 'pr:in-review', 'jules'
|
|
304
|
+
];
|
|
305
|
+
for (const label of toRemove) {
|
|
306
|
+
await github.rest.issues.removeLabel({ owner, repo, issue_number, name: label }).catch(() => {});
|
|
307
|
+
}
|
|
308
|
+
console.log(`Issue #${issue_number} labels cleaned up`);
|
|
@@ -64,7 +64,7 @@ jobs:
|
|
|
64
64
|
--max-time 30 || echo "API_ERROR")
|
|
65
65
|
|
|
66
66
|
if [ "$RESPONSE" = "API_ERROR" ]; then
|
|
67
|
-
gh
|
|
67
|
+
GH_TOKEN="$PROJECT_TOKEN" gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" --method POST -f 'labels[]=infra:qa-broken'
|
|
68
68
|
gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** Could not reach GitHub Models API. Manual review required."
|
|
69
69
|
exit 0
|
|
70
70
|
fi
|
|
@@ -73,13 +73,13 @@ jobs:
|
|
|
73
73
|
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 "")')
|
|
74
74
|
|
|
75
75
|
if echo "$VERDICT" | grep -q "^PASS"; then
|
|
76
|
-
gh
|
|
76
|
+
GH_TOKEN="$PROJECT_TOKEN" gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" --method POST -f 'labels[]=qa:approved'
|
|
77
77
|
gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** AC coverage verified. ${EXPLANATION}"
|
|
78
78
|
elif echo "$VERDICT" | grep -q "^FAIL"; then
|
|
79
|
-
gh
|
|
79
|
+
GH_TOKEN="$PROJECT_TOKEN" gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" --method POST -f 'labels[]=qa:needs-work'
|
|
80
80
|
gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** AC coverage insufficient. ${EXPLANATION}"
|
|
81
81
|
else
|
|
82
|
-
gh
|
|
82
|
+
GH_TOKEN="$PROJECT_TOKEN" gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" --method POST -f 'labels[]=infra:qa-broken'
|
|
83
83
|
gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** Could not parse GitHub Models response. Manual review required."
|
|
84
84
|
fi
|
|
85
85
|
|
package/AGENTS.md
CHANGED
|
@@ -27,7 +27,7 @@ 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. **Initial State**: When beginning work on a new issue, your very first action must be to apply the `stage:
|
|
30
|
+
1. **Initial State**: When beginning work on a new issue, your very first action must be to apply the `stage:brainstorming` label using the GitHub CLI (`gh issue edit <N> --add-label "stage:brainstorming"`).
|
|
31
31
|
2. Read the issue entirely — understand its type (US/BUG/TASK/SPIKE) and the Acceptance Criteria.
|
|
32
32
|
3. Read `docs/pdlc.md` — understand the PDLC and the Definition of Done in this project.
|
|
33
33
|
4. Read all files mentioned in the issue's technical context.
|