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
@@ -19,7 +19,7 @@ jobs:
19
19
  STATUS_FIELD_ID: "PVTSSF_lAHODpFFL84BXg7hzhStRHI"
20
20
  STATUS_CODE_REVIEW_PR: "86ca9720"
21
21
  steps:
22
- - uses: actions/checkout@v4
22
+ - uses: actions/checkout@v5.0.1
23
23
  with:
24
24
  fetch-depth: 0
25
25
 
@@ -34,7 +34,7 @@ jobs:
34
34
  HEAD="${{ github.event.pull_request.head.sha }}"
35
35
 
36
36
  # Get PR diff (truncated to 8000 chars to stay within context limits)
37
- DIFF=$(git diff "$BASE" "$HEAD" | head -c 64000)
37
+ DIFF=$(git diff "$BASE" "$HEAD" | head -c 8000)
38
38
 
39
39
  # Extract linked issues from PR body
40
40
  PR_BODY=$(gh pr view "$PR_NUMBER" --json body --jq '.body // ""')
@@ -53,39 +53,50 @@ jobs:
53
53
  AC_CONTEXT="No linked issue found. Evaluate if the PR description is self-contained."
54
54
  fi
55
55
 
56
- # Serialize prompt as JSON string and call GitHub Models API (30s timeout)
56
+ # Serialize prompt as JSON string and call GitHub Models API (3 attempts, 20s backoff)
57
57
  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()))')
58
58
 
59
- RESPONSE=$(curl -sf -X POST \
60
- "https://models.github.ai/inference/chat/completions" \
61
- -H "Authorization: Bearer ${GITHUB_TOKEN}" \
62
- -H "Content-Type: application/json" \
63
- -d "{\"model\":\"gpt-4o-mini\",\"messages\":[{\"role\":\"user\",\"content\":${PROMPT_JSON}}]}" \
64
- --max-time 30 || echo "API_ERROR")
59
+ RESPONSE="API_ERROR"
60
+ for attempt in 1 2 3; do
61
+ RESULT=$(curl -s -X POST \
62
+ "https://models.github.ai/inference/chat/completions" \
63
+ -H "Authorization: Bearer ${GITHUB_TOKEN}" \
64
+ -H "Content-Type: application/json" \
65
+ -d "{\"model\":\"gpt-4o-mini\",\"messages\":[{\"role\":\"user\",\"content\":${PROMPT_JSON}}]}" \
66
+ -w "\n__HTTP_STATUS__:%{http_code}" \
67
+ --max-time 45 2>/dev/null)
68
+ HTTP_STATUS=$(echo "$RESULT" | grep -o '__HTTP_STATUS__:[0-9]*' | cut -d: -f2)
69
+ BODY=$(echo "$RESULT" | sed 's/__HTTP_STATUS__:[0-9]*$//')
70
+ echo "Attempt $attempt: HTTP $HTTP_STATUS"
71
+ if [ "$HTTP_STATUS" = "200" ]; then RESPONSE="$BODY"; break; fi
72
+ [ $attempt -lt 3 ] && sleep 20
73
+ done
65
74
 
66
75
  if [ "$RESPONSE" = "API_ERROR" ]; then
67
- gh pr edit "$PR_NUMBER" --add-label "infra:qa-broken"
76
+ GH_TOKEN="$PROJECT_TOKEN" gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" --method POST -f 'labels[]=infra:qa-broken'
68
77
  gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** Could not reach GitHub Models API. Manual review required."
69
- exit 0
78
+ # exit 1 marks this check as failed; qa-gate.yml enforces the merge block via infra:qa-broken label
79
+ exit 1
70
80
  fi
71
81
 
72
82
  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")')
73
83
  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
84
 
75
85
  if echo "$VERDICT" | grep -q "^PASS"; then
76
- gh pr edit "$PR_NUMBER" --add-label "qa:approved"
86
+ GH_TOKEN="$PROJECT_TOKEN" gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" --method POST -f 'labels[]=qa:approved'
77
87
  gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** AC coverage verified. ${EXPLANATION}"
78
88
  elif echo "$VERDICT" | grep -q "^FAIL"; then
79
- gh pr edit "$PR_NUMBER" --add-label "qa:needs-work"
89
+ GH_TOKEN="$PROJECT_TOKEN" gh api "repos/${GITHUB_REPOSITORY}/issues/${PR_NUMBER}/labels" --method POST -f 'labels[]=qa:needs-work'
80
90
  gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** AC coverage insufficient. ${EXPLANATION}"
81
91
  else
82
- 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'
83
93
  gh pr comment "$PR_NUMBER" --body "🤖 **QA Agent:** Could not parse GitHub Models response. Manual review required."
94
+ exit 1
84
95
  fi
85
96
 
86
97
  - name: Move board card to Code Review on qa:approved
87
98
  if: ${{ env.PROJECT_TOKEN != '' && env.PROJECT_ID != '{{PROJECT_ID}}' }}
88
- uses: actions/github-script@v7
99
+ uses: actions/github-script@v8
89
100
  with:
90
101
  github-token: ${{ env.PROJECT_TOKEN }}
91
102
  script: |
@@ -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
package/AGENTS.md CHANGED
@@ -27,14 +27,55 @@ 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:exploration` label using the GitHub CLI (`gh issue edit <N> --add-label "stage:exploration"`).
31
- 2. Read the issue entirely — understand its type (US/BUG/TASK/SPIKE) and the Acceptance Criteria.
32
- 3. Read `docs/pdlc.md` — understand the PDLC and the Definition of Done in this project.
33
- 4. Read all files mentioned in the issue's technical context.
34
- 5. Implement the **minimum viable change** that satisfies the ACs — do not refactor beyond scope.
35
- 6. Run tests: `echo "No tests/build needed."`
36
- 7. Run typecheck: `echo "No typecheck needed."`
37
- 8. Create a Pull Request with `Closes #N` in the body — automation moves the board.
30
+ 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**:
31
+ - `spec:approved` → begin implementation (gate already passed)
32
+ - `stage:development` or `stage:testing` → issue is owned by automation; do not intervene unless explicitly asked to fix a specific problem
33
+ - `stage:approval` → spec already written; wait for PM to add `spec:approved` before doing anything
34
+ 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`.
35
+ 3. Read the issue entirely — understand its type (US/BUG/TASK/SPIKE) and the Acceptance Criteria.
36
+ 4. Read `docs/pdlc.md` — understand the PDLC and the Definition of Done in this project.
37
+ 5. Read all files mentioned in the issue's technical context.
38
+ 6. Implement the **minimum viable change** that satisfies the ACs — do not refactor beyond scope.
39
+ 7. Run tests: `echo "No tests/build needed."`
40
+ 8. Run typecheck: `echo "No typecheck needed."`
41
+ 9. Create a Pull Request with `Closes #N` in the body — automation moves the board.
42
+
43
+ ## Spec Format
44
+
45
+ When writing or rewriting an issue body during detailing, include ALL sections below. Omitting any section blocks `stage:approval`.
46
+
47
+ ```
48
+ ## Problem
49
+ [1-3 sentences. What fails. Who affected. Measured impact.]
50
+
51
+ ## Sprint Goal / Success Metrics
52
+ | Metric | Baseline | Target | When |
53
+ |--------|----------|--------|------|
54
+
55
+ ## Solution
56
+ [Behavioral description of what is built. No implementation details.]
57
+
58
+ ## Acceptance Criteria
59
+ **AC1 — [name]**
60
+ - Given [precondition]
61
+ - When [action]
62
+ - Then [outcome]
63
+
64
+ ## Edge Cases
65
+ - EC1: [condition] → [expected behavior]
66
+
67
+ ## Out of Scope
68
+ - [item] — reason
69
+
70
+ ## Non-Functional Requirements
71
+ - Performance: [metric with number]
72
+ - Security: [constraint]
73
+ - Reliability: [constraint]
74
+ > For pure docs/markdown issues with zero runtime behavior, include the NFRs section and state "N/A".
75
+
76
+ ## Files to Modify
77
+ - `path/to/file` — what changes
78
+ ```
38
79
 
39
80
  ## What NOT to do
40
81
 
@@ -50,3 +91,4 @@ Always start from the current `main` HEAD. Never work over stale snapshots.
50
91
  - **Lint/Types:** `echo "No tests/build needed."`
51
92
  - **Typecheck:** `echo "No typecheck needed."`
52
93
  - **Build:** `echo "No tests/build needed."`
94
+ - **Canonical secret name:** `PROJECT_TOKEN` (not `PROJECT_PAT`) — use this in all workflow files, both live and templates
package/CLAUDE.md CHANGED
@@ -1,9 +1,59 @@
1
+ # agentic-pdlc
2
+
3
+ **What it is:** npm CLI (`npx create-agentic-pdlc`) that installs a PDLC workflow for AI agent projects. Stack: Markdown + GitHub Actions YAML only — never complex Node/Python/Bash scripts.
4
+
5
+ **Workflow:** `stage:brainstorming` → `stage:detailing` → `spec:approved` → `stage:development` → PR → merge. Labels move the board automatically.
6
+
7
+ ## Session Startup
8
+
9
+ Read: `AGENTS.md` (mandatory contract), `docs/pdlc.md` (board + labels — only when operating on the board).
10
+ Run: `gh issue list --state open --label "stage:development" --json number,title --jq '.[] | "#\(.number) \(.title)"'`
11
+
1
12
  # PDLC Stage Gate
2
13
 
3
14
  NEVER run `gh pr create` unless one of these is true:
4
- - The linked issue has label `stage:approval`
15
+ - The linked issue has label `spec:approved`
5
16
  - The branch name starts with `hotfix/`
6
17
 
7
- Advance stages first: `exploration` → `brainstorming` → `detailing` → `approval`
18
+ NEVER edit files, create branches, or commit unless the linked issue has label `spec:approved` (set by human PM only) or the branch name starts with `hotfix/`.
19
+
20
+ Advance stages first: `brainstorming` → `detailing` → `approval` → (human adds `spec:approved`) → `development`
21
+
22
+ The PreToolUse hook will block `gh pr create` automatically if this rule is violated.
23
+
24
+ ## Human-in-the-Loop
25
+
26
+ | Transition | Gate |
27
+ |---|---|
28
+ | → `stage:brainstorming` | Autonomous — apply immediately |
29
+ | → `stage:detailing` | Ask user — present problem summary + options, wait for choice |
30
+ | → `stage:approval` | **Autonomous** — agent completes spec end-to-end, advances without asking |
31
+ | `spec:approved` | **Human PM only** — agent waits; never adds this label |
32
+ | → `stage:development` | Human applies `spec:approved` label — that IS the gate |
33
+
34
+ **Detailing is fully autonomous.** Write the complete spec, add it to the issue, advance to `stage:approval` — no confirmation needed. Then **stop and wait** for human to add `spec:approved` before any implementation.
35
+
36
+ **Spec 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.
37
+
38
+ ## Stage Transition Rules (non-negotiable)
39
+
40
+ MUST apply `stage:brainstorming` label immediately on starting work — before
41
+ reading any code, before invoking any skill. Then read context and present
42
+ problem summary + 2–3 solution options in a single message.
43
+
44
+ MUST NOT add `stage:detailing` label until the user has explicitly selected
45
+ an approach in the current conversation turn. Work done in a prior
46
+ planning session does NOT count as confirmation.
47
+
48
+ MUST NOT add `spec:approved` or any approval-trigger label under any
49
+ circumstances — these are set by the PM (human) only, after reviewing the spec
50
+ in the issue body. Adding them triggers irreversible automation (Jules dispatch,
51
+ board move).
52
+
53
+ MUST NOT add or remove `stage:development`, `spec:approved`, or `qa:*` labels —
54
+ these are owned by GitHub Actions automation and the PM. The agent is responsible
55
+ for applying `stage:brainstorming`, `stage:detailing`, and `stage:approval` as
56
+ part of the prescribed workflow above.
8
57
 
9
- The PreToolUse hook will block the action automatically if this rule is violated.
58
+ Each stage transition requires a fresh explicit signal from the user in the same
59
+ session where the transition happens. These rules have no exceptions.
package/SETUP.md CHANGED
@@ -12,6 +12,8 @@ Estimated time: 2-3 hours (including GitHub Projects setup).
12
12
  - GitHub Projects enabled on your account/organization
13
13
  - Implementation agent connected to the repository (e.g., Jules: github.com/google-labs/jules)
14
14
 
15
+ > **Jules users:** After installing the Jules GitHub App at [github.com/settings/installations](https://github.com/settings/installations), set `JULES_ENABLED=true` at **repo → Settings → Variables → Actions** to enable Jules dispatch. If this variable is absent, agent comments are silently skipped — no false "dispatched" messages.
16
+
15
17
  ---
16
18
 
17
19
  ## Step 1 — Create the GitHub Project Board
@@ -61,7 +63,7 @@ npx create-agentic-pdlc
61
63
  The CLI will:
62
64
  1. Ask you which AI Agent you use (Claude Code, Cursor, etc.).
63
65
  2. Copy the system instructions pointing to our interactive Setup Mode.
64
- 3. Automatically download the base templates to `.agentic-pdlc/templates/`.
66
+ 3. Automatically install the base templates into your project.
65
67
 
66
68
  Once the CLI finishes, it will instruct you to open your AI agent and run the **Setup Mode**. Your AI agent will then ask you the required project variables interactively and generate `AGENTS.md`, `docs/pdlc.md`, and the GitHub Actions for you!
67
69
 
@@ -167,6 +169,7 @@ The issue appears in your GitHub notifications automatically — zero extra setu
167
169
  ```bash
168
170
  cp .agentic-pdlc/templates/.github/workflows/agentic-metrics.yml .github/workflows/agentic-metrics.yml
169
171
  ```
172
+ > If the file is missing, re-run `npx create-agentic-pdlc` to update your installed templates.
170
173
 
171
174
  2. Commit and push. The first pulse runs next Sunday, or trigger it manually:
172
175
  ```bash
@@ -48,6 +48,10 @@ If any of these files are missing, you are in **Setup Mode**. Do not proceed wit
48
48
  - a) **No** — *No autonomous implementation agent.*
49
49
  - b) **@google-labs-jules** — *Jules (recommended if you don't have one).*
50
50
  - c) **Other** — *Enter the agent's handle.*
51
+
52
+ When writing `agent-trigger.yml`, set `{{IMPLEMENTATION_AGENT_LABEL}}` as follows:
53
+ - Jules (`@google-labs-jules`): use `jules` — this is the native label the Jules GitHub App watches. **Do NOT use `agent:jules`** — Jules does not watch that label and the trigger will silently fail.
54
+ - Other agents: use the handle without `@`, lowercase (e.g. `@my-agent` → `my-agent`).
51
55
  5. Generate and write the missing files replacing the `{{SCREAMING_SNAKE_CASE}}` placeholders using the templates in `.agentic-pdlc/templates/`.
52
56
  6. Offer to run the `gh` commands for labels (`spec:approved`, `pr:in-review`, `pr:approved`, `architecture-violation`).
53
57
  7. **`PROJECT_PAT` secret (required for board automation):**
@@ -98,28 +102,28 @@ If `AGENTS.md` and `docs/pdlc.md` are present, you are in **Execution Mode**.
98
102
 
99
103
  ### 0. [FIRST] Issue Type Identification
100
104
 
101
- **Run before anything else — before `stage:exploration`, before reading code.**
105
+ **Run before anything else — before reading code.**
102
106
 
103
- Reading the issue title and body for type inference is exempt from the `stage:exploration` requirement: it is metadata already present in the request, not code reading or skill invocation.
107
+ Reading the issue title and body for type inference is exempt from the initial label requirement: it is metadata already present in the request, not code reading or skill invocation.
104
108
 
105
- 1. Check if issue already has a `type:*` label (`type:us`, `type:task`, `type:bug`, `type:spike`) → if yes, skip to Section 0.1.
109
+ 1. Check if issue already has a `type:*` label (`type:feature`, `type:task`, `type:bug`, `type:spike`) → if yes, skip to Section 0.1.
106
110
  2. Read issue title + body (metadata only — no code reading at this step).
107
111
  3. Classify using these rules:
108
112
  - `type:task` — operational change, config, rename, docs update, non-functional (no user-facing behavior change)
109
113
  - `type:bug` — something broken that should work
110
114
  - `type:spike` — research/evaluation spike, never reaches Development
111
- - `type:us` — new feature, behavioral change, anything product-facing
115
+ - `type:feature` — new feature, behavioral change, anything product-facing
112
116
  4. Confidence â‰Ĩ 85% → add inferred label: `gh issue edit <N> --add-label "type:<inferred>"`
113
- 5. Confidence < 85% → default to `type:us`: `gh issue edit <N> --add-label "type:us"`
117
+ 5. Confidence < 85% → default to `type:feature`: `gh issue edit <N> --add-label "type:feature"`
114
118
 
115
119
  **Type drives the PDLC flow:**
116
120
 
117
121
  | Type | Flow |
118
122
  |---|---|
119
- | `type:us` | Full flow: exploration → brainstorming → Gate 1 → detailing → approval |
120
- | `type:task` | Skip brainstorming: exploration → detailing → approval |
121
- | `type:bug` | Skip brainstorming: exploration → detailing → approval |
122
- | `type:spike` | Skip brainstorming: exploration → detailing → conclusion comment (never reaches Development) |
123
+ | `type:feature` | brainstorming → Gate 1 → detailing → approval |
124
+ | `type:task` | brainstorming → Gate 1 → detailing → approval |
125
+ | `type:bug` | brainstorming → Gate 1 → detailing → approval |
126
+ | `type:spike` | brainstorming → Gate 1 → detailing → conclusion comment (never reaches Development) |
123
127
 
124
128
  ### 0.1 Board Labels — Mandatory at Every State Transition
125
129
 
@@ -127,11 +131,10 @@ These label commands are non-negotiable. They run **before** the activity they a
127
131
 
128
132
  | When | Command |
129
133
  |---|---|
130
- | Before reading any code / invoking any skill | `gh issue edit <N> --add-label "stage:exploration"` |
131
- | Before presenting architecture approaches | `gh issue edit <N> --add-label "stage:brainstorming" --remove-label "stage:exploration"` |
134
+ | Before reading any code / invoking any skill | `gh issue edit <N> --add-label "stage:brainstorming"` |
132
135
  | Before writing the technical spec | `gh issue edit <N> --add-label "stage:detailing" --remove-label "stage:brainstorming"` |
133
136
 
134
- No investigation, no skill invocation, no code reading happens before `stage:exploration` is applied. No architecture presentation starts before `stage:brainstorming` is set (and `stage:exploration` removed). No spec writing starts before `stage:detailing` is set (and `stage:brainstorming` removed).
137
+ No investigation, no skill invocation, no code reading happens before `stage:brainstorming` is applied. No spec writing starts before `stage:detailing` is set (and `stage:brainstorming` removed).
135
138
 
136
139
  ### 0.1 PR Stage Gate — Non-Negotiable
137
140
 
@@ -147,25 +150,46 @@ git checkout -b hotfix/<N>-<description>
147
150
  ```
148
151
 
149
152
  ### 1. Daily Upstream Loop
150
- Your job is to move issues from "💡 Idea - don't move manually to Exploration" to "📐 Detail Solution".
153
+ Your job is to move issues from "💡 Idea" to "📐 Detail Solution".
151
154
  When asked to work on a feature, you will:
152
155
  - Explore the code context.
153
156
  - Present architectural approaches (Brainstorming).
154
157
  - Stop and wait for the human PM's explicit approval (Gate 1).
155
158
 
156
159
  ### 2. Creating the Spec
157
- Once approved, you will detail the solution directly into the GitHub Issue body. Focus on precise Acceptance Criteria.
158
- **IMPORTANT:** You must always rewrite the full issue body to include both the user story and the Acceptance Criteria. Do not simply append the ACs to the existing text. Use this format:
160
+ Once approved, detail the solution directly into the GitHub Issue body. Always rewrite the full issue body — never append only ACs to existing text. Include ALL sections below. Omitting any section blocks `stage:approval`. Use this format:
159
161
 
160
162
  ```
161
- **As** [user],
162
- **I want** [action],
163
- **so that** [benefit].
163
+ ## Problem
164
+ [1-3 sentences. What fails. Who affected. Measured impact.]
164
165
 
165
- ---
166
+ ## Sprint Goal / Success Metrics
167
+ | Metric | Baseline | Target | When |
168
+ |--------|----------|--------|------|
169
+
170
+ ## Solution
171
+ [Behavioral description of what is built. No implementation details.]
166
172
 
167
173
  ## Acceptance Criteria
168
- ...
174
+ **AC1 — [name]**
175
+ - Given [precondition]
176
+ - When [action]
177
+ - Then [outcome]
178
+
179
+ ## Edge Cases
180
+ - EC1: [condition] → [expected behavior]
181
+
182
+ ## Out of Scope
183
+ - [item] — reason
184
+
185
+ ## Non-Functional Requirements
186
+ - Performance: [metric with number]
187
+ - Security: [constraint]
188
+ - Reliability: [constraint]
189
+ > For pure docs/markdown issues with zero runtime behavior, include the NFRs section and state "N/A".
190
+
191
+ ## Files to Modify
192
+ - `path/to/file` — what changes
169
193
  ```
170
194
 
171
195
  ### 3. Handoff
@@ -26,19 +26,14 @@ fi
26
26
 
27
27
  LABELS=$(gh issue view "$ISSUE_NUM" --json labels --jq '[.labels[].name] | join(" ")' 2>/dev/null || echo "")
28
28
 
29
- if echo "$LABELS" | grep -qw "stage:approval"; then
29
+ if echo "$LABELS" | grep -qw "spec:approved" || echo "$LABELS" | grep -qw "stage:approval" || echo "$LABELS" | grep -qw "stage:development" || echo "$LABELS" | grep -qw "stage:testing" || echo "$LABELS" | grep -qw "human-approved"; then
30
30
  echo "✅ PDLC: Issue #$ISSUE_NUM approved — gate passed."
31
31
  exit 0
32
32
  fi
33
33
 
34
- if echo "$LABELS" | grep -qw "stage:development"; then
35
- echo "✅ PDLC: Issue #$ISSUE_NUM in development (spec already approved) — gate passed."
36
- exit 0
37
- fi
38
-
39
34
  STAGE=$(echo "$LABELS" | tr ' ' '\n' | grep "^stage:" | head -1 || echo "none")
40
35
  echo "❌ PDLC Stage Gate: Issue #$ISSUE_NUM is not approved."
41
36
  echo " Current stage: $STAGE"
42
- echo " Required: stage:approval or stage:development label on the issue."
37
+ echo " Required: stage:approval OR spec:approved OR stage:development OR stage:testing OR human-approved label on the issue."
43
38
  echo " Emergency bypass: rename branch to hotfix/<issue-number>-<description>."
44
39
  exit 1
package/bin/cli.js CHANGED
@@ -41,10 +41,10 @@ const i18n = {
41
41
  invalid_repo: t('❌ Invalid repository URL. Expected format: https://github.com/OWNER/REPO', '❌ URL de repositÃŗrio invÃĄlida. Formato esperado: https://github.com/OWNER/REPO', '❌ URL de repositorio invÃĄlida. Formato esperado: https://github.com/OWNER/REPO'),
42
42
  ask_org: t('Does this repository belong to a personal User account (e.g., github.com/rafaeltcosta86) or an Organization (e.g., github.com/google-labs)? (user/org): ', 'Esse repositÃŗrio pertence a um UsuÃĄrio pessoal (ex: github.com/rafaeltcosta86) ou a uma OrganizaÃ§ÃŖo (ex: github.com/google-labs)? (user/org): ', 'ÂŋEste repositorio pertenece a un Usuario personal (ej: github.com/rafaeltcosta86) o a una OrganizaciÃŗn (ej: github.com/google-labs)? (user/org): '),
43
43
  starting_setup: t('Starting automated repository setup...', 'Iniciando o setup automatizado do repositÃŗrio...', 'Iniciando la configuraciÃŗn automatizada del repositorio...'),
44
- creating_labels: t('[1/2] Creating repository labels...', '[1/2] Criando labels no repositÃŗrio...', '[1/2] Creando etiquetas (labels) en el repositorio...'),
44
+ creating_labels: t('[1/3] Creating repository labels...', '[1/3] Criando labels no repositÃŗrio...', '[1/3] Creando etiquetas (labels) en el repositorio...'),
45
45
  label_ok: t('✅ Label created: ', '✅ Label criada: ', '✅ Etiqueta creada: '),
46
46
  label_warn: t('âš ī¸ Failed to create label (might already exist): ', 'âš ī¸ Falha ao criar label (talvez jÃĄ exista): ', 'âš ī¸ Fallo al crear etiqueta (quizÃĄs ya exista): '),
47
- creating_project: t('[2/2] Creating Project V2 Board...', '[2/2] Criando Project V2 Board...', '[2/2] Creando Project V2 Board...'),
47
+ creating_project: t('[2/3] Creating Project V2 Board...', '[2/3] Criando Project V2 Board...', '[2/3] Creando Project V2 Board...'),
48
48
  project_ok: t('✅ Project created (ID: ', '✅ Projeto criado (ID: ', '✅ Proyecto creado (ID: '),
49
49
  project_err: t('❌ Failed to create project. Error: ', '❌ Falha ao criar o projeto. Erro: ', '❌ Fallo al crear el proyecto. Error: '),
50
50
  link_project_ok: t('✅ Project linked to repository.', '✅ Projeto vinculado ao repositÃŗrio.', '✅ Proyecto vinculado al repositorio.'),
@@ -72,6 +72,9 @@ const i18n = {
72
72
  update_qa_ask: t(' Activate? Uses GITHUB_TOKEN — no extra secrets needed. (Y/n): ', ' Ativar? Usa GITHUB_TOKEN — nenhum secret extra necessÃĄrio. (S/n): ', ' ÂŋActivar? Usa GITHUB_TOKEN — sin secrets adicionales. (S/n): '),
73
73
  update_sentinel_header: t('— Sentinel (architecture audit via Gemini Code Assist) —', '— Sentinel (auditoria de arquitetura via Gemini Code Assist) —', '— Sentinel (auditoría de arquitectura via Gemini Code Assist) —'),
74
74
  update_sentinel_ask: t(' Activate? Requires Gemini Code Assist CI job. (Y/n): ', ' Ativar? Requer CI job do Gemini Code Assist. (S/n): ', ' ÂŋActivar? Requiere CI job de Gemini Code Assist. (S/n): '),
75
+ configuring_protection: t('[3/3] Configuring branch protection...', '[3/3] Configurando proteÃ§ÃŖo de branch...', '[3/3] Configurando protecciÃŗn de rama...'),
76
+ protection_ok: t('✅ Branch protection set — required checks: PDLC Stage Gate, QA Gate.', '✅ ProteÃ§ÃŖo de branch configurada — checks obrigatÃŗrios: PDLC Stage Gate, QA Gate.', '✅ ProtecciÃŗn de rama configurada — checks requeridos: PDLC Stage Gate, QA Gate.'),
77
+ protection_warn: t('âš ī¸ Branch protection could not be set automatically.\n Set required checks manually: Settings → Branches → main → Required status checks.\n Required: "PDLC Stage Gate" and "QA Gate"', 'âš ī¸ ProteÃ§ÃŖo de branch nÃŖo pôde ser configurada automaticamente.\n Configure manualmente: Settings → Branches → main → Required status checks.\n ObrigatÃŗrios: "PDLC Stage Gate" e "QA Gate"', 'âš ī¸ No se pudo configurar la protecciÃŗn de rama automÃĄticamente.\n ConfigÃēralo en: Settings → Branches → main → Required status checks.\n Requeridos: "PDLC Stage Gate" y "QA Gate"'),
75
78
  };
76
79
 
77
80
  const cyan = '\x1b[36m';
@@ -227,6 +230,16 @@ async function runSetup() {
227
230
  }
228
231
  }
229
232
 
233
+ const defaultLabels = [
234
+ 'bug', 'documentation', 'duplicate', 'enhancement',
235
+ 'good first issue', 'help wanted', 'invalid', 'question', 'wontfix'
236
+ ];
237
+ for (const label of defaultLabels) {
238
+ try {
239
+ execFileSync('gh', ['label', 'delete', label, '--repo', repo, '--yes'], { stdio: 'ignore' });
240
+ } catch (_) {}
241
+ }
242
+
230
243
  // Project V2
231
244
  console.log(`\n${cyan}${i18n.creating_project}${reset}`);
232
245
  let ownerId, projectId, projectNumber;
@@ -240,13 +253,13 @@ async function runSetup() {
240
253
  }
241
254
 
242
255
  const projectCreateRaw = execFileSync('gh', ['api', 'graphql', '-f', 'query=mutation($owner: ID!, $title: String!) { createProjectV2(input: {ownerId: $owner, title: $title}) { projectV2 { id number } } }', '-f', `owner=${ownerId}`, '-f', `title=${boardName}`], { stdio: ['ignore', 'pipe', 'pipe'] }).toString().trim();
243
- const projectCreateResponse = JSON.parse(projectCreateRaw);
244
- if (projectCreateResponse.errors) {
256
+ const projectCreateResponse = projectCreateRaw ? JSON.parse(projectCreateRaw) : null;
257
+ if (projectCreateResponse?.errors) {
245
258
  throw new Error(projectCreateResponse.errors.map(e => e.message).join('; '));
246
259
  }
247
- const projectCreateData = projectCreateResponse.data.createProjectV2.projectV2;
248
- projectId = projectCreateData.id;
249
- projectNumber = projectCreateData.number;
260
+ const projectCreateData = projectCreateResponse?.data?.createProjectV2?.projectV2;
261
+ projectId = projectCreateData?.id;
262
+ projectNumber = projectCreateData?.number;
250
263
 
251
264
  console.log(` ${i18n.project_ok}${projectId})`);
252
265
 
@@ -280,7 +293,7 @@ async function runSetup() {
280
293
 
281
294
  if (statusFieldId) {
282
295
  const columns = [
283
- { name: "💡 Idea", description: "Backlog — every new issue lands here", color: "GRAY" },
296
+ { name: "💡 Idea - No move to Exploration directly", description: "Just tell your agent to work on issue #XX", color: "GRAY" },
284
297
  { name: "🔍 Exploration", description: "AI is analyzing code and context", color: "PURPLE" },
285
298
  { name: "🧠 Brainstorming", description: "AI proposed approaches and trade-offs", color: "PINK" },
286
299
  { name: "📐 Detail Solution", description: "AI is writing the technical spec", color: "BLUE" },
@@ -314,7 +327,8 @@ async function runSetup() {
314
327
 
315
328
  const updateOutput = execFileSync('gh', ['api', 'graphql', '--input', '-'], { input: queryPayload }).toString().trim();
316
329
  const jsonResponse = updateOutput ? JSON.parse(updateOutput) : null;
317
- const returnedOptions = jsonResponse?.data?.updateProjectV2Field?.projectV2Field?.options || [];
330
+ const returnedOptions = jsonResponse?.data?.updateProjectV2Field?.projectV2Field?.options ||
331
+ jsonResponse?.data?.updateProjectV2SingleSelectField?.projectV2SingleSelectField?.options || [];
318
332
 
319
333
  for (const opt of returnedOptions) {
320
334
  optionMap[opt.name] = opt.id;
@@ -344,6 +358,24 @@ async function runSetup() {
344
358
  console.log(`\n${yellow}â„šī¸ Org repo detected — PROJECT_PAT will require manual setup for security.${reset}`);
345
359
  }
346
360
 
361
+ // Branch protection — require PDLC Stage Gate + QA Gate on default branch
362
+ console.log(`\n${cyan}${i18n.configuring_protection}${reset}`);
363
+ try {
364
+ const defaultBranch = execFileSync('gh', ['api', `repos/${repo}`, '--jq', '.default_branch'],
365
+ { stdio: ['ignore', 'pipe', 'ignore'], encoding: 'utf8' }).trim() || 'main';
366
+ const protectionPayload = JSON.stringify({
367
+ required_status_checks: { strict: false, contexts: ['PDLC Stage Gate', 'QA Gate'] },
368
+ enforce_admins: false,
369
+ required_pull_request_reviews: null,
370
+ restrictions: null
371
+ });
372
+ execFileSync('gh', ['api', `repos/${repo}/branches/${defaultBranch}/protection`, '--method', 'PUT', '--input', '-'],
373
+ { input: protectionPayload, stdio: ['pipe', 'ignore', 'pipe'] });
374
+ console.log(` ${green}${i18n.protection_ok}${reset}`);
375
+ } catch (_) {
376
+ console.log(` ${yellow}${i18n.protection_warn}${reset}`);
377
+ }
378
+
347
379
  console.log(`\n${yellow}${i18n.scaffolding}${reset}`);
348
380
 
349
381
  // We copy the templates folder so the agent has the real text logic to replace and rename
package/docs/flow.md CHANGED
@@ -5,8 +5,7 @@ This document describes the full lifecycle of a card on the agentic-pdlc board
5
5
  ```mermaid
6
6
  stateDiagram-v2
7
7
  direction LR
8
- Idea --> Exploration : stage:exploration
9
- Exploration --> Brainstorming : stage:brainstorming
8
+ Idea --> Brainstorming : stage:brainstorming
10
9
  Brainstorming --> Detailing : Gate 1 (PM)
11
10
  Detailing --> Approval : stage:approval
12
11
  Approval --> Development : Gate 2 (spec:approved)
@@ -23,7 +22,7 @@ stateDiagram-v2
23
22
  |------|---------------|
24
23
  | **PM** (human) | Selects issues for the sprint, approves brainstorm (Gate 1), approves spec (Gate 2) |
25
24
  | **TL / Reviewer** (human) | Co-approves spec for technical decisions (Gate 2), reviews and approves the PR (Gate 3) |
26
- | **Claude** | Exploration, brainstorming, spec writing — acts on PM instruction via chat or via upstream label |
25
+ | **Claude** | Brainstorming (context reading + approaches), spec writing — acts on PM instruction via chat or via upstream label |
27
26
  | **Implementation Agent** | Implementation, running tests, opening the PR |
28
27
  | **Workflow** | All label swaps and card movements — the source of truth for board state |
29
28
 
@@ -38,33 +37,22 @@ Issue exists in the backlog with no `stage:` label.
38
37
 
39
38
  ---
40
39
 
41
- ### 🔍 Exploration
42
-
43
- **Trigger (two equivalent paths):**
44
- - PM tells Claude directly in chat → Claude adds `stage:exploration` to the issue, OR
45
- - PM adds `stage:exploration` directly to the issue
46
-
47
- **Workflow:** `project-automation.yml` detects `stage:exploration` → moves card to Exploration.
48
-
49
- **Who works:** Claude reads relevant code and context.
50
-
51
- ---
52
-
53
40
  ### 🧠 Brainstorming
54
41
 
55
- **Trigger:** Claude, after exploration.
42
+ **Trigger:** PM tells Claude to work on the issue (in chat) or applies `stage:brainstorming` directly.
56
43
 
57
44
  **Actions:**
58
- - Claude posts a comment on the issue with findings and 2–3 proposed approaches
59
- - Claude swaps `stage:exploration` → `stage:brainstorming`
45
+ - Claude applies `stage:brainstorming` immediately
46
+ - Claude reads relevant code and context
47
+ - Claude posts a single comment with: (1) brief problem summary, (2) 2–3 proposed approaches with trade-offs
60
48
 
61
- **Workflow:** `project-automation.yml` moves card to Brainstorming.
49
+ **Workflow:** `project-automation.yml` detects `stage:brainstorming` → moves card to Brainstorming.
62
50
 
63
51
  **⏸ Human gate (Gate 1 — PM):** PM reads the brainstorming comment and selects an approach. This can be done:
64
52
  - By commenting on the issue (e.g., "Option A", "Go with B", "approved", "lgtm")
65
53
  - By telling Claude in chat
66
54
 
67
- **Note on implicit approval:** If Claude presented multiple options, selecting one (e.g., "Option A") counts as implicit approval. The `upstream-gate.yml` detects option-selection patterns in addition to explicit approval words.
55
+ **Note on implicit approval:** Selecting one option (e.g., "Option A") counts as implicit approval. The `upstream-gate.yml` detects option-selection patterns in addition to explicit approval words.
68
56
 
69
57
  ---
70
58
 
@@ -141,7 +129,6 @@ Issue exists in the backlog with no `stage:` label.
141
129
 
142
130
  | Label | Added by | Removed by |
143
131
  |-------|----------|------------|
144
- | `stage:exploration` | PM (human) or Claude | Claude |
145
132
  | `stage:brainstorming` | Claude | `upstream-gate.yml` |
146
133
  | `stage:detailing` | `upstream-gate.yml` | Claude |
147
134
  | `stage:approval` | Claude | `agent-trigger.yml` |