create-agentic-pdlc 1.1.1 → 2.0.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.
@@ -5,8 +5,8 @@ on:
5
5
  types: [opened, reopened, closed]
6
6
  pull_request_review:
7
7
  types: [submitted]
8
- issue_comment:
9
- types: [created]
8
+ issues:
9
+ types: [labeled]
10
10
 
11
11
  env:
12
12
  PROJECT_ID: "{{PROJECT_ID}}"
@@ -15,45 +15,52 @@ env:
15
15
  STATUS_BRAINSTORMING: "{{ID_BRAINSTORMING}}"
16
16
  STATUS_DETAILING: "{{ID_DETAILING}}"
17
17
  STATUS_APPROVAL: "{{ID_APPROVAL}}"
18
- STATUS_CODE_REVIEW: "{{ID_CODE_REVIEW}}"
19
- STATUS_PULL_REQUEST: "{{ID_PULL_REQUEST}}"
20
- STATUS_PRODUCAO: "{{ID_PRODUCAO}}"
18
+ STATUS_DEVELOPMENT: "{{ID_DEVELOPMENT}}"
19
+ STATUS_TESTING: "{{ID_TESTING}}"
20
+ STATUS_CODE_REVIEW_PR: "{{ID_CODE_REVIEW_PR}}"
21
+ STATUS_PRODUCTION: "{{ID_PRODUCTION}}"
21
22
 
22
23
  jobs:
23
- # Issue Comment → Move Upstream
24
- move-card-on-comment:
25
- name: Upstream Comment Marker → Move Card
26
- if: github.event_name == 'issue_comment' && github.event.action == 'created'
24
+ # Issue Labeled → Move Upstream
25
+ move-card-on-label:
26
+ name: Upstream Label → Move Card
27
+ if: github.event_name == 'issues' && github.event.action == 'labeled'
27
28
  runs-on: ubuntu-latest
28
29
  env:
29
30
  PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
30
31
  steps:
31
- - name: Detect Marker and Move Issue
32
+ - name: Detect Label and Move Issue
32
33
  if: ${{ env.PROJECT_TOKEN != '' }}
33
34
  uses: actions/github-script@v7
34
35
  with:
35
36
  github-token: ${{ env.PROJECT_TOKEN }}
36
37
  script: |
37
- const body = context.payload.comment.body;
38
+ const labelName = context.payload.label.name;
38
39
  let targetStatusId = null;
39
40
  let stageName = null;
40
41
 
41
- if (body.includes('<!-- PDLC:stage:exploration -->')) {
42
+ if (labelName === 'upstream:exploration') {
42
43
  targetStatusId = process.env.STATUS_EXPLORATION;
43
44
  stageName = 'Exploration';
44
- } else if (body.includes('<!-- PDLC:stage:brainstorming -->')) {
45
+ } else if (labelName === 'upstream:brainstorming') {
45
46
  targetStatusId = process.env.STATUS_BRAINSTORMING;
46
47
  stageName = 'Brainstorming';
47
- } else if (body.includes('<!-- PDLC:stage:detailing -->')) {
48
+ } else if (labelName === 'upstream:detailing') {
48
49
  targetStatusId = process.env.STATUS_DETAILING;
49
50
  stageName = 'Detailing';
50
- } else if (body.includes('<!-- PDLC:stage:approval -->')) {
51
+ } else if (labelName === 'upstream:approval') {
51
52
  targetStatusId = process.env.STATUS_APPROVAL;
52
53
  stageName = 'Approval';
54
+ } else if (labelName === 'upstream:development') {
55
+ targetStatusId = process.env.STATUS_DEVELOPMENT;
56
+ stageName = 'Development';
57
+ } else if (labelName === 'upstream:testing') {
58
+ targetStatusId = process.env.STATUS_TESTING;
59
+ stageName = 'Testing';
53
60
  }
54
61
 
55
62
  if (!targetStatusId) {
56
- console.log('No upstream PDLC marker found. Skipping.');
63
+ console.log('No upstream PDLC label found. Skipping.');
57
64
  return;
58
65
  }
59
66
 
@@ -79,16 +86,17 @@ jobs:
79
86
  await moveItem(node_id, targetStatusId);
80
87
  console.log(`Issue #${number} moved to ${stageName}`);
81
88
 
89
+ {{OPTIONAL_ARCHITECTURE_VIOLATION_JOB}}
82
90
 
83
- # PR Opened → Move linked issue to Code Review
91
+ # PR Opened → Move linked issue to Code Review / PR
84
92
  move-card-on-pr-open:
85
- name: Open PR → Code Review
93
+ name: Open PR → Code Review / PR
86
94
  if: github.event_name == 'pull_request' && (github.event.action == 'opened' || github.event.action == 'reopened')
87
95
  runs-on: ubuntu-latest
88
96
  env:
89
97
  PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
90
98
  steps:
91
- - name: Move linked issue to Code Review
99
+ - name: Move linked issue to Code Review / PR
92
100
  if: ${{ env.PROJECT_TOKEN != '' }}
93
101
  uses: actions/github-script@v7
94
102
  with:
@@ -117,7 +125,7 @@ jobs:
117
125
  }
118
126
  }`, {
119
127
  p: process.env.PROJECT_ID, i: item.id, f: process.env.STATUS_FIELD_ID,
120
- v: { singleSelectOptionId: process.env.STATUS_CODE_REVIEW }
128
+ v: { singleSelectOptionId: process.env.STATUS_CODE_REVIEW_PR }
121
129
  });
122
130
  };
123
131
 
@@ -125,24 +133,24 @@ jobs:
125
133
  for (const n of linkedIssues) {
126
134
  const { data: issue } = await github.rest.issues.get({ owner, repo, issue_number: n });
127
135
  await moveItem(issue.node_id);
128
- console.log(`Issue #${n} → Code Review`);
136
+ console.log(`Issue #${n} → Code Review / PR`);
129
137
  }
130
138
  } else {
131
139
  await moveItem(pr.node_id);
132
- console.log(`PR #${prNumber} → Code Review (no linked issue)`);
140
+ console.log(`PR #${prNumber} → Code Review / PR (no linked issue)`);
133
141
  }
134
142
 
135
- await github.rest.issues.addLabels({ owner, repo, issue_number: prNumber, labels: ['pr:review'] }).catch(() => {});
143
+ await github.rest.issues.addLabels({ owner, repo, issue_number: prNumber, labels: ['pr:in-review'] }).catch(() => {});
136
144
 
137
- # Review Approved → Pull Request
145
+ # Review Approved → Add Label
138
146
  move-card-on-review-approved:
139
- name: Approved PR → Pull Request
147
+ name: Approved PR → Add Label
140
148
  if: github.event_name == 'pull_request_review' && github.event.review.state == 'approved'
141
149
  runs-on: ubuntu-latest
142
150
  env:
143
151
  PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
144
152
  steps:
145
- - name: Move issue to Pull Request
153
+ - name: Swap PR labels
146
154
  if: ${{ env.PROJECT_TOKEN != '' }}
147
155
  uses: actions/github-script@v7
148
156
  with:
@@ -150,34 +158,7 @@ jobs:
150
158
  script: |
151
159
  const prNumber = context.payload.pull_request.number;
152
160
  const { owner, repo } = context.repo;
153
- const { data: pr } = await github.rest.pulls.get({ owner, repo, pull_number: prNumber });
154
- const body = pr.body ?? '';
155
- const linkedIssues = [...body.matchAll(/(?:Closes?|Fixes?|Resolves?)\s+#(\d+)/gi)].map(m => parseInt(m[1]));
156
-
157
- const moveItem = async (nodeId) => {
158
- const { addProjectV2ItemById: { item } } = await github.graphql(`
159
- mutation($p: ID!, $c: ID!) {
160
- addProjectV2ItemById(input: {projectId: $p, contentId: $c}) { item { id } }
161
- }`, { p: process.env.PROJECT_ID, c: nodeId });
162
- await github.graphql(`
163
- mutation($p: ID!, $i: ID!, $f: ID!, $v: ProjectV2FieldValue!) {
164
- updateProjectV2ItemFieldValue(input: {projectId: $p, itemId: $i, fieldId: $f, value: $v}) {
165
- projectV2Item { id }
166
- }
167
- }`, { p: process.env.PROJECT_ID, i: item.id, f: process.env.STATUS_FIELD_ID,
168
- v: { singleSelectOptionId: process.env.STATUS_PULL_REQUEST } });
169
- };
170
-
171
- if (linkedIssues.length > 0) {
172
- for (const n of linkedIssues) {
173
- const { data: issue } = await github.rest.issues.get({ owner, repo, issue_number: n });
174
- await moveItem(issue.node_id);
175
- }
176
- } else {
177
- await moveItem(pr.node_id);
178
- }
179
-
180
- try { await github.rest.issues.removeLabel({ owner, repo, issue_number: prNumber, name: 'pr:review' }); } catch {}
161
+ try { await github.rest.issues.removeLabel({ owner, repo, issue_number: prNumber, name: 'pr:in-review' }); } catch {}
181
162
  await github.rest.issues.addLabels({ owner, repo, issue_number: prNumber, labels: ['pr:approved'] }).catch(() => {});
182
163
 
183
164
  # PR Merged → Production
@@ -211,7 +192,7 @@ jobs:
211
192
  projectV2Item { id }
212
193
  }
213
194
  }`, { p: process.env.PROJECT_ID, i: item.id, f: process.env.STATUS_FIELD_ID,
214
- v: { singleSelectOptionId: process.env.STATUS_PRODUCAO } });
195
+ v: { singleSelectOptionId: process.env.STATUS_PRODUCTION } });
215
196
  };
216
197
 
217
198
  if (linkedIssues.length > 0) {
@@ -0,0 +1,54 @@
1
+ name: Upstream Gate 1
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [created]
6
+
7
+ jobs:
8
+ evaluate-gate:
9
+ name: Evaluate Brainstorming Approval
10
+ if: ${{ !github.event.issue.pull_request && contains(github.event.issue.labels.*.name, 'upstream:brainstorming') }}
11
+ runs-on: ubuntu-latest
12
+ env:
13
+ PROJECT_TOKEN: ${{ secrets.PROJECT_TOKEN }}
14
+ steps:
15
+ - name: Check for approval and swap label
16
+ if: ${{ env.PROJECT_TOKEN != '' }}
17
+ uses: actions/github-script@v7
18
+ with:
19
+ github-token: ${{ env.PROJECT_TOKEN }}
20
+ script: |
21
+ const comment = context.payload.comment.body.toLowerCase();
22
+ const isApproved =
23
+ comment.includes('approved') ||
24
+ comment.includes('lgtm') ||
25
+ /option\s+[a-z0-9]/i.test(comment) ||
26
+ /go\s+with\s+[a-z0-9]/i.test(comment) ||
27
+ /proceed/i.test(comment);
28
+
29
+ if (isApproved) {
30
+ const { owner, repo } = context.repo;
31
+ const issue_number = context.payload.issue.number;
32
+
33
+ console.log('Approval detected, swapping labels...');
34
+
35
+ try {
36
+ await github.rest.issues.removeLabel({
37
+ owner,
38
+ repo,
39
+ issue_number,
40
+ name: 'upstream:brainstorming'
41
+ });
42
+ } catch (e) {
43
+ console.log('Could not remove upstream:brainstorming label');
44
+ }
45
+
46
+ await github.rest.issues.addLabels({
47
+ owner,
48
+ repo,
49
+ issue_number,
50
+ labels: ['upstream:detailing']
51
+ });
52
+ } else {
53
+ console.log('No approval pattern detected in the comment.');
54
+ }
@@ -35,7 +35,33 @@ Always start from the current `main` HEAD. Never work over stale snapshots.
35
35
  3. Read all files mentioned in the issue's technical context.
36
36
  4. Implement the **minimum viable change** that satisfies the ACs — do not refactor beyond scope.
37
37
  5. Run tests: `{{TEST_COMMAND}}`
38
- 6. Create a Pull Request with `Closes #N` in the body — automation moves the board.
38
+ 6. Run typecheck (if applicable): `{{TYPECHECK_COMMAND}}`
39
+ 7. Create a Pull Request with `Closes #N` in the body — automation moves the board.
40
+
41
+ ### Spec format (Upstream Agents)
42
+
43
+ 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:
44
+
45
+ ```
46
+ **As** [user],
47
+ **I want** [action],
48
+ **so that** [benefit].
49
+
50
+ ---
51
+
52
+ ## Acceptance Criteria
53
+
54
+ **AC1 — ...**
55
+ - Given ...
56
+ - When ...
57
+ - Then ...
58
+
59
+ **AC2 — ...**
60
+ ...
61
+
62
+ ## Files to modify
63
+ - `path/to/file.ts` — what changes
64
+ ```
39
65
 
40
66
  ## What NOT to do
41
67
 
@@ -49,5 +75,6 @@ Always start from the current `main` HEAD. Never work over stale snapshots.
49
75
 
50
76
  - **Tests:** `{{TEST_COMMAND}}`
51
77
  - **Lint/Types:** `{{LINT_COMMAND}}`
78
+ - **Typecheck:** `{{TYPECHECK_COMMAND}}`
52
79
  - **Build:** `{{BUILD_COMMAND}}`
53
80
  {{EXTRA_PATTERNS}}
@@ -4,20 +4,20 @@
4
4
 
5
5
  | Column | Meaning | Who moves the card |
6
6
  |---|---|---|
7
- | 💡 Idea | Backlog — every new issue lands here | Claude Code / Manual |
8
- | 🔍 Exploration | Claude is analyzing code and context | Claude Code |
9
- | 🧠 Brainstorming | Claude proposed approaches, awaiting PM gate | Claude Code |
10
- | 📐 Detail Solution | Claude is writing the technical spec | Claude Code |
11
- | ✅ Approval | Spec ready, awaiting `spec:approved` label | Claude Code |
12
- | ⚙️ Development | Agent implementing the spec | Jules / Implementation Agent |
7
+ | 💡 Idea | Backlog — every new issue lands here | Manual |
8
+ | 🔍 Exploration | Claude is analyzing code and context | Label `stage:exploration` |
9
+ | 🧠 Brainstorming | Claude proposed approaches, awaiting PM gate | Label `stage:brainstorming` |
10
+ | 📐 Detail Solution | Claude is writing the technical spec | Label `stage:detailing` |
11
+ | ✅ Approval | Spec ready, awaiting `spec:approved` label | Label `spec:approved` |
12
+ | ⚙️ Development | Agent implementing the spec | Label `stage:development` |
13
13
  | 🧪 Testing | CI pipeline running | GitHub Actions |
14
- | 👁 Code Review | PR opened, awaiting human review | GitHub Actions |
15
- | 🔀 Pull Request | PR approved, awaiting merge | GitHub Actions |
14
+ | 👁 Code Review / PR | PR opened, awaiting human review | GitHub Actions |
15
+ | 🔀 Merge | PR approved, awaiting merge | GitHub Actions |
16
16
  | 🚀 Production | Merged | GitHub Actions |
17
17
 
18
18
  <!--
19
19
  Adapt columns as needed. The functional baseline is:
20
- 💡 Idea → ⚙️ Development → 👁 Code Review → 🚀 Production
20
+ 💡 Idea → ⚙️ Development → 👁 Code Review / PR → 🚀 Production
21
21
  -->
22
22
 
23
23
  ## Board Identifiers (GitHub Projects)
@@ -39,8 +39,8 @@ REPO = {{REPO_OWNER}}/{{REPO_NAME}}
39
39
  | ✅ Approval | `{{ID_APPROVAL}}` |
40
40
  | ⚙️ Development | `{{ID_DEVELOPMENT}}` |
41
41
  | 🧪 Testing | `{{ID_TESTING}}` |
42
- | 👁 Code Review | `{{ID_CODE_REVIEW}}` |
43
- | 🔀 Pull Request | `{{ID_PULL_REQUEST}}` |
42
+ | 👁 Code Review / PR | `{{ID_CODE_REVIEW_PR}}` |
43
+ | 🔀 Merge | `{{ID_MERGE}}` |
44
44
  | 🚀 Production | `{{ID_PRODUCTION}}` |
45
45
 
46
46
  ## Agent × Phase Mapping
@@ -49,7 +49,7 @@ REPO = {{REPO_OWNER}}/{{REPO_NAME}}
49
49
  |---|---|
50
50
  | 💡 → 📐 (upstream) | Claude (or ideation agent) in conversational session |
51
51
  | ⚙️ → 🔀 (downstream) | {{IMPLEMENTATION_AGENT}} (e.g. Jules `@google-labs-jules`) |
52
- | 👁 Code Review | Human (you) |
52
+ | 👁 Code Review / PR | Human (you) |
53
53
  | Automatic transitions | GitHub Actions |
54
54
 
55
55
  ## Issue Title Conventions
@@ -67,8 +67,12 @@ REPO = {{REPO_OWNER}}/{{REPO_NAME}}
67
67
 
68
68
  | Label | Entity | Color | Meaning |
69
69
  |---|---|---|---|
70
+ | `stage:exploration` | Issue | Purple | Issue is being evaluated |
71
+ | `stage:brainstorming` | Issue | Pink | Proposed approaches awaiting PM gate |
72
+ | `stage:detailing` | Issue | Blue | Technical spec is being written |
73
+ | `stage:development` | Issue | Orange | Agent is implementing the spec |
70
74
  | `spec:approved` | Issue | Green | Gate 2 — agent is cleared to implement |
71
- | `pr:review` | PR | Yellow | Awaiting code review |
75
+ | `pr:in-review` | PR | Yellow | Awaiting code review |
72
76
  | `pr:approved` | PR | Green | Code review approved |
73
77
 
74
78
  ## Approval Gates