create-agentic-pdlc 2.0.3 → 2.0.5

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/SETUP.md CHANGED
@@ -114,24 +114,18 @@ git push
114
114
 
115
115
  ---
116
116
 
117
- ## Step 7 — Populate the Initial Backlog
117
+ ## Step 7 — Ignite the Backlog
118
118
 
119
- For each known idea or feature, create an issue using the convention:
119
+ Forget heavy templates and CLI commands. Just drop your raw idea and let the AI do the heavy lifting:
120
120
 
121
- ```bash
122
- gh issue create \
123
- --repo owner/repo \
124
- --title "👤 US: [short description]" \
125
- --body "**As** [user],
126
- **I want** [action],
127
- **so that** [benefit].
128
-
129
- ---
130
-
131
- Initial idea issue. Spec to be detailed."
132
- ```
121
+ 1. Open your **GitHub Project** board.
122
+ 2. Under the **Idea** column, click **`+ Add item`**.
123
+ 3. Type your feature title and hit **Enter**.
124
+ 4. Select **Blank issue**.
125
+ 5. In the right sidebar, add a brief description of what you want.
126
+ 6. Ask your AI Assistant to read the issue and write the full specification!
133
127
 
134
- Move the issues to the `Idea` column on the board matching your setup.
128
+ Your AI will handle the refinement and automatically move it to the `Specification` stage.
135
129
 
136
130
  ---
137
131
 
@@ -19,8 +19,9 @@ Specifically, check for:
19
19
  - `.github/workflows/pdlc-health-check.yml`
20
20
 
21
21
  If any of these files are missing, you are in **Setup Mode**. Do not proceed with feature requests until setup is complete.
22
- 1. Acknowledge that the framework is not yet set up.
23
- 2. Interactively ask the user for required values **one group at a time**:
22
+ 1. **Language Detection:** Analyze the user's previous prompts and preferred language. Conduct this entire Setup Mode and ask all your interactive questions in that same language.
23
+ 2. Acknowledge that the framework is not yet set up.
24
+ 3. Interactively ask the user for required values **one group at a time**:
24
25
  - **Project basics:** Project Name, Description, Technical Stack (Structure), and GitHub Username (for CODEOWNERS security).
25
26
  - **Commands:** Test command, Lint command, Build command.
26
27
  - **Invariants:** Critical business rules agents must never violate (e.g. Human-in-the-loop).
@@ -31,7 +32,8 @@ If any of these files are missing, you are in **Setup Mode**. Do not proceed wit
31
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).
32
33
  4. Offer to run the `gh` commands for labels (`spec:approved`, `pr:in-review`, `pr:approved`, `architecture-violation`).
33
34
  5. Commit everything with the message: `chore: setup agentic-pdlc framework`.
34
- 6. Conclude Setup Mode.
35
+ 6. **IMPORTANT:** Delete this setup prompt file (e.g., `.agentic-setup.md`, `.agentic-setup-prompt.md`, or `.agentic-pdlc/SETUP_PROMPT.md`) from the root or `.agentic-pdlc/` directory to clean up the workspace.
36
+ 7. Conclude Setup Mode.
35
37
 
36
38
  ---
37
39
 
package/bin/cli.js CHANGED
@@ -3,6 +3,7 @@
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
5
  const readline = require('readline');
6
+ const { execSync, execFileSync } = require('child_process');
6
7
 
7
8
  // The directory where CLI is executed
8
9
  const targetDir = process.cwd();
@@ -14,13 +15,72 @@ const rl = readline.createInterface({
14
15
  output: process.stdout
15
16
  });
16
17
 
18
+ function askQuestion(query) {
19
+ return new Promise(resolve => rl.question(query, resolve));
20
+ }
21
+
22
+ // Detect language
23
+ const locale = Intl.DateTimeFormat().resolvedOptions().locale || 'en-US';
24
+ const isPt = locale.toLowerCase().startsWith('pt');
25
+ const isEs = locale.toLowerCase().startsWith('es');
26
+
27
+ function t(en, pt, es) {
28
+ if (isPt) return pt;
29
+ if (isEs) return es || en; // Fallback para inglês se faltar espanhol
30
+ return en;
31
+ }
32
+
33
+ const i18n = {
34
+ welcome: t('🤖 Welcome to Agentic PDLC Boilerplate Bootstrap! 🤖', '🤖 Bem-vindo ao Agentic PDLC Boilerplate Bootstrap! 🤖', '🤖 ¡Bienvenido a Agentic PDLC Boilerplate Bootstrap! 🤖'),
35
+ checking_gh: t('Checking GitHub CLI (gh) installation...', 'Verificando instalação do GitHub CLI (gh)...', 'Verificando la instalación de GitHub CLI (gh)...'),
36
+ gh_ok: t('✅ GitHub CLI is authenticated.', '✅ GitHub CLI está autenticado.', '✅ GitHub CLI está autenticado.'),
37
+ gh_error: t('❌ GitHub CLI (gh) is not installed or not authenticated.', '❌ GitHub CLI (gh) não está instalado ou não autenticado.', '❌ GitHub CLI (gh) no está instalado o no está autenticado.'),
38
+ gh_install: t('Please install it from https://cli.github.com/ and run "gh auth login" before continuing.\n', 'Por favor, instale em https://cli.github.com/ e rode "gh auth login" antes de continuar.\n', 'Por favor, instálalo desde https://cli.github.com/ y ejecuta "gh auth login" antes de continuar.\n'),
39
+ ask_agent: t('Which AI Agent will you use for the setup? (e.g. claude, cursor, copilot, antigravity, or other): ', 'Qual Agente de IA você usará para o setup? (ex: claude, cursor, copilot, antigravity, ou outro): ', '¿Qué Agente de IA usarás para la configuración? (ej: claude, cursor, copilot, antigravity, u otro): '),
40
+ ask_repo: t('What is your GitHub repository URL? (e.g., https://github.com/YOUR_USER/repo_name): ', 'Qual é a URL do seu repositório no GitHub? (ex: https://github.com/SEU_USUARIO/repo_name): ', '¿Cuál es la URL de tu repositorio en GitHub? (ej: https://github.com/TU_USUARIO/repo_name): '),
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
+ 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
+ ask_branch: t('What is your main branch name? (default: main): ', 'Qual o nome da sua branch principal? (padrão: main): ', '¿Cuál es el nombre de tu rama principal? (por defecto: main): '),
44
+ starting_setup: t('Starting automated repository setup...', 'Iniciando o setup automatizado do repositório...', 'Iniciando la configuración automatizada del repositorio...'),
45
+ creating_labels: t('[1/2] Creating repository labels...', '[1/2] Criando labels no repositório...', '[1/2] Creando etiquetas (labels) en el repositorio...'),
46
+ label_ok: t('✅ Label created: ', '✅ Label criada: ', '✅ Etiqueta creada: '),
47
+ 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): '),
48
+ applying_protection: t('[2/3] Applying branch protection on ', '[2/3] Aplicando proteção de branch em ', '[2/3] Aplicando protección de rama en '),
49
+ protection_ok: t('✅ Branch protection applied to ', '✅ Proteção de branch aplicada em ', '✅ Protección de rama aplicada a '),
50
+ protection_warn: t('⚠️ Failed to apply branch protection. (Do you have GitHub Pro or is the repo Public?)', '⚠️ Falha ao aplicar proteção de branch. (Você tem GitHub Pro ou o repo é Público?)', '⚠️ Fallo al aplicar protección de rama. (¿Tienes GitHub Pro o el repositorio es Público?)'),
51
+ creating_project: t('[2/2] Creating Project V2 Board...', '[2/2] Criando Project V2 Board...', '[2/2] Creando Project V2 Board...'),
52
+ project_ok: t('✅ Project created (ID: ', '✅ Projeto criado (ID: ', '✅ Proyecto creado (ID: '),
53
+ project_err: t('❌ Failed to create project. Error: ', '❌ Falha ao criar o projeto. Erro: ', '❌ Fallo al crear el proyecto. Error: '),
54
+ config_columns: t('Configuring Project Columns...', 'Configurando colunas do Projeto...', 'Configurando columnas del Proyecto...'),
55
+ columns_ok: t('✅ Project columns configured successfully.', '✅ Colunas do projeto configuradas com sucesso.', '✅ Columnas del proyecto configuradas con éxito.'),
56
+ columns_warn: t('⚠️ Failed to configure project columns. You may need to add them manually.', '⚠️ Falha ao configurar colunas. Você pode precisar adicioná-las manualmente.', '⚠️ Fallo al configurar columnas. Es posible que debas agregarlas manualmente.'),
57
+ scaffolding: t('Scaffolding Agentic PDLC into your project...', 'Injetando Agentic PDLC no seu projeto...', 'Inyectando Agentic PDLC en tu proyecto...'),
58
+ templates_copied: t('✅ Templates copied to .agentic-pdlc/templates/', '✅ Templates copiados para .agentic-pdlc/templates/', '✅ Plantillas copiadas a .agentic-pdlc/templates/'),
59
+ pdlc_prefilled: t('✅ Pre-filled pdlc.md with Project ID, Status Field ID, and Column Option IDs.', '✅ pdlc.md preenchido com Project ID, Status Field ID, e Column Option IDs.', '✅ pdlc.md completado con Project ID, Status Field ID y Column Option IDs.'),
60
+ setup_written: t('✅ Setup agent profile written to .agentic-setup.md\n', '✅ Perfil de setup do agente salvo em .agentic-setup.md\n', '✅ Perfil de configuración del agente guardado en .agentic-setup.md\n'),
61
+ framework_scaffolded: t('🎉 Framework files scaffolded to .agentic-pdlc/templates/', '🎉 Arquivos do framework injetados em .agentic-pdlc/templates/', '🎉 Archivos del framework inyectados en .agentic-pdlc/templates/'),
62
+ next_steps: t('👉 NEXT STEPS:', '👉 PRÓXIMOS PASSOS:', '👉 PRÓXIMOS PASOS:'),
63
+ step_1: t('1. Open your AI Assistant (Claude, Cursor, Copilot, etc).', '1. Abra o seu Assistente de IA (Claude, Cursor, Copilot, etc).', '1. Abre tu Asistente de IA (Claude, Cursor, Copilot, etc).'),
64
+ step_2: t('2. Ask it to read the .agentic-setup.md and start Setup Mode in any language you prefer. Example 👇', '2. Peça para ele ler o .agentic-setup.md e iniciar o Setup Mode. Exemplo 👇', '2. Pídele que lea .agentic-setup.md e inicie el Setup Mode. Ejemplo 👇'),
65
+ note_cleanup: t('Note: The agent will clean up the .agentic-setup.md file automatically when finished.\n', 'Nota: O agente irá limpar o arquivo .agentic-setup.md automaticamente quando terminar.\n', 'Nota: El agente limpiará el archivo .agentic-setup.md automáticamente cuando termine.\n'),
66
+ missing_claude: t('❌ Could not find instruction file at ', '❌ Não foi possível encontrar o arquivo de instrução em ', '❌ No se pudo encontrar el archivo de instrucción en '),
67
+ cursor_rules_written: t('✅ Default cursor rules written to .cursorrules', '✅ Regras padrão do cursor salvas em .cursorrules', '✅ Reglas por defecto de cursor guardadas en .cursorrules'),
68
+ cursor_setup_written: t('✅ Framework Setup Instructions written to .agentic-pdlc/SETUP_PROMPT.md', '✅ Instruções de Setup do Framework salvas em .agentic-pdlc/SETUP_PROMPT.md', '✅ Instrucciones de Setup del Framework guardadas en .agentic-pdlc/SETUP_PROMPT.md'),
69
+ cursor_done: t('🎉 Done! To start the conversational setup:', '🎉 Pronto! Para iniciar o setup conversacional:', '🎉 ¡Listo! Para iniciar la configuración conversacional:'),
70
+ cursor_step_1: t('\t1. Open Cursor', '\t1. Abra o Cursor', '\t1. Abre Cursor'),
71
+ cursor_step_2: t('\t2. Open Composer (Cmd+I or Cmd+L) and type: "@.agentic-pdlc/SETUP_PROMPT.md execute Setup Mode"\n', '\t2. Abra o Composer (Cmd+I ou Cmd+L) e digite: "@.agentic-pdlc/SETUP_PROMPT.md execute Setup Mode"\n', '\t2. Abre Composer (Cmd+I o Cmd+L) y escribe: "@.agentic-pdlc/SETUP_PROMPT.md execute Setup Mode"\n'),
72
+ generic_written: t('✅ Agent generic setup instructions written to .agentic-setup.md', '✅ Instruções genéricas salvas em .agentic-setup.md', '✅ Instrucciones genéricas guardadas en .agentic-setup.md'),
73
+ generic_done: t('Tell your AI agent to read and execute the .agentic-setup.md file!\n', 'Diga ao seu agente para ler e executar o arquivo .agentic-setup.md!\n', '¡Dile a tu agente de IA que lea y ejecute el archivo .agentic-setup.md!\n')
74
+ };
75
+
17
76
  const cyan = '\x1b[36m';
18
77
  const reset = '\x1b[0m';
19
78
  const green = '\x1b[32m';
20
79
  const yellow = '\x1b[33m';
80
+ const red = '\x1b[31m';
21
81
 
22
82
  console.log(`${cyan}================================================================${reset}`);
23
- console.log(`${cyan}🤖 Welcome to Agentic PDLC Boilerplate Bootstrap! 🤖${reset}`);
83
+ console.log(`${cyan}${i18n.welcome}${reset}`);
24
84
  console.log(`${cyan}================================================================${reset}\n`);
25
85
 
26
86
  // Helper function to recursively copy directories
@@ -39,10 +99,167 @@ function copyDirSync(src, dest) {
39
99
  }
40
100
  }
41
101
 
42
- rl.question('Which AI Agent will you use for the setup? (e.g. claude, cursor, copilot, or other): ', (answer) => {
43
- const agent = answer.trim().toLowerCase();
44
-
45
- console.log(`\n${yellow}Scaffolding Agentic PDLC into your project...${reset}`);
102
+ async function runSetup() {
103
+ console.log(`${yellow}${i18n.checking_gh}${reset}`);
104
+ try {
105
+ execSync('gh auth status', { stdio: 'ignore' });
106
+ console.log(`${green}${i18n.gh_ok}${reset}\n`);
107
+ } catch (error) {
108
+ console.error(`${red}${i18n.gh_error}${reset}`);
109
+ console.error(`${i18n.gh_install}`);
110
+ process.exit(1);
111
+ }
112
+
113
+ const agentAnswer = await askQuestion(i18n.ask_agent);
114
+ const agent = agentAnswer.trim().toLowerCase();
115
+ if (!['claude', 'cursor', 'copilot'].includes(agent)) {
116
+ console.log(t(`ℹ️ Generating Universal Setup for '${agent}' (Compatible with any Markdown-reading agent).`, `ℹ️ Gerando Setup Universal para '${agent}' (Compatível com qualquer agente que leia Markdown).`, `ℹ️ Generando Setup Universal para '${agent}' (Compatible con cualquier agente que lea Markdown).`));
117
+ }
118
+
119
+ let repoOwner, repoName, repo;
120
+ while (true) {
121
+ let repoUrl = (await askQuestion(i18n.ask_repo)).trim();
122
+ if (repoUrl.endsWith('/')) repoUrl = repoUrl.slice(0, -1);
123
+ if (repoUrl.endsWith('.git')) repoUrl = repoUrl.slice(0, -4);
124
+ const repoParts = repoUrl.split('/');
125
+ if (repoParts.length >= 2) {
126
+ repoOwner = repoParts[repoParts.length - 2];
127
+ repoName = repoParts[repoParts.length - 1];
128
+ repo = `${repoOwner}/${repoName}`;
129
+ break;
130
+ }
131
+ console.log(`${red}${i18n.invalid_repo}${reset}`);
132
+ }
133
+
134
+ const askProjectName = t(`What is the project name for the board? (default: ${repoName.toUpperCase()}): `, `Qual o nome do projeto em que o board será configurado? (padrão: ${repoName.toUpperCase()}): `, `¿Cuál es el nombre del proyecto en el que se configurará el board? (por defecto: ${repoName.toUpperCase()}): `);
135
+ const projectNameAnswer = await askQuestion(askProjectName);
136
+ const projectName = projectNameAnswer.trim() ? projectNameAnswer.trim().toUpperCase() : repoName.toUpperCase();
137
+ const boardName = `BOARD - ${projectName}`;
138
+
139
+ let isOrg = false;
140
+ try {
141
+ const ownerType = execFileSync('gh', ['api', `repos/${repo}`, '--jq', '.owner.type']).toString().trim();
142
+ isOrg = ownerType === 'Organization';
143
+ } catch (err) {
144
+ const accountTypeAnswer = await askQuestion(i18n.ask_org);
145
+ isOrg = accountTypeAnswer.trim().toLowerCase() === 'org' || accountTypeAnswer.trim().toLowerCase() === 'organization';
146
+ }
147
+
148
+ let branchName = 'main';
149
+ try {
150
+ branchName = execFileSync('gh', ['api', `repos/${repo}`, '--jq', '.default_branch']).toString().trim() || 'main';
151
+ } catch (err) {
152
+ const branchAnswer = await askQuestion(i18n.ask_branch);
153
+ if (branchAnswer.trim()) branchName = branchAnswer.trim();
154
+ }
155
+
156
+ console.log(`\n${yellow}${i18n.starting_setup}${reset}`);
157
+
158
+ // Labels
159
+ const labels = [
160
+ { name: 'stage:exploration', color: '9b59b6', description: 'Issue is being evaluated' },
161
+ { name: 'stage:brainstorming', color: 'e84393', description: 'Proposed approaches awaiting PM gate' },
162
+ { name: 'stage:detailing', color: '3498db', description: 'Technical spec is being written' },
163
+ { name: 'stage:development', color: 'e67e22', description: 'Agent is implementing the spec' },
164
+ { name: 'stage:testing', color: '8e44ad', description: 'Agent is testing the implementation' },
165
+ { name: 'spec:approved', color: '0e8a16', description: 'Spec approved — agent can implement' },
166
+ { name: 'pr:in-review', color: 'e4e669', description: 'PR awaiting code review' },
167
+ { name: 'pr:approved', color: '0e8a16', description: 'PR approved, ready for merge' },
168
+ { name: 'architecture-violation', color: 'd93f0b', description: 'Invariant violation detected by CI' },
169
+ { name: 'qa:approved', color: '0e8a16', description: 'QA Agent approved the implementation' },
170
+ { name: 'qa:needs-work', color: 'd93f0b', description: 'QA Agent found issues' },
171
+ { name: 'jules', color: '5319e7', description: 'Jules AI Agent' }
172
+ ];
173
+
174
+ console.log(`\n${cyan}${i18n.creating_labels}${reset}`);
175
+ for (const label of labels) {
176
+ try {
177
+ execFileSync('gh', ['label', 'create', label.name, '--color', label.color, '--description', label.description, '--repo', repo, '--force'], { stdio: 'ignore' });
178
+ console.log(` ${i18n.label_ok}${label.name}`);
179
+ } catch (err) {
180
+ console.log(` ${i18n.label_warn}${label.name}`);
181
+ }
182
+ }
183
+
184
+ // Project V2
185
+ console.log(`\n${cyan}${i18n.creating_project}${reset}`);
186
+ let ownerId, projectId;
187
+ try {
188
+ if (isOrg) {
189
+ const orgOutput = execFileSync('gh', ['api', 'graphql', '-f', 'query=query($login: String!) { organization(login: $login) { id } }', '-f', `login=${repoOwner}`, '--jq', '.data.organization.id']).toString().trim();
190
+ ownerId = orgOutput;
191
+ } else {
192
+ const userOutput = execFileSync('gh', ['api', 'graphql', '-f', 'query={ viewer { id } }', '--jq', '.data.viewer.id']).toString().trim();
193
+ ownerId = userOutput;
194
+ }
195
+
196
+ const projectCreateOutput = execFileSync('gh', ['api', 'graphql', '-f', 'query=mutation($owner: ID!, $title: String!) { createProjectV2(input: {ownerId: $owner, title: $title}) { projectV2 { id } } }', '-f', `owner=${ownerId}`, '-f', `title=${boardName}`, '--jq', '.data.createProjectV2.projectV2.id']).toString().trim();
197
+ projectId = projectCreateOutput;
198
+
199
+ console.log(` ${i18n.project_ok}${projectId})`);
200
+ } catch (err) {
201
+ console.log(` ${i18n.project_err}${err.message}`);
202
+ }
203
+
204
+ let statusFieldId;
205
+ let optionMap = {};
206
+
207
+ if (projectId) {
208
+ console.log(` ${cyan}${i18n.config_columns}${reset}`);
209
+ try {
210
+ const fieldsOutput = execFileSync('gh', ['api', 'graphql', '-f', 'query=query($projectId: ID!) { node(id: $projectId) { ... on ProjectV2 { fields(first: 20) { nodes { ... on ProjectV2SingleSelectField { id name } } } } } }', '-f', `projectId=${projectId}`, '--jq', '.data.node.fields.nodes[] | select(.name == "Status") | .id']).toString().trim();
211
+ statusFieldId = fieldsOutput;
212
+
213
+ if (statusFieldId) {
214
+ const columns = [
215
+ { name: "💡 Idea", description: "Backlog", color: "GRAY" },
216
+ { name: "🔍 Exploration", description: "Claude is analyzing", color: "PURPLE" },
217
+ { name: "🧠 Brainstorming", description: "Awaiting PM gate", color: "PINK" },
218
+ { name: "📐 Detail Solution", description: "Technical spec", color: "BLUE" },
219
+ { name: "✅ Approval", description: "Spec ready", color: "GREEN" },
220
+ { name: "⚙️ Development", description: "Agent implementing", color: "ORANGE" },
221
+ { name: "🧪 Testing", description: "QA testing", color: "RED" },
222
+ { name: "👁 Code Review / PR", description: "PR opened", color: "YELLOW" },
223
+ { name: "🚀 Production", description: "Merged", color: "GREEN" }
224
+ ];
225
+
226
+ const updateFieldQuery = `mutation($fieldId: ID!, $options: [ProjectV2SingleSelectFieldOptionInput!]) {
227
+ updateProjectV2Field(input: {
228
+ fieldId: $fieldId,
229
+ singleSelectOptions: $options
230
+ }) {
231
+ projectV2Field {
232
+ ... on ProjectV2SingleSelectField {
233
+ options { id name }
234
+ }
235
+ }
236
+ }
237
+ }`;
238
+
239
+ const queryPayload = JSON.stringify({
240
+ query: updateFieldQuery,
241
+ variables: {
242
+ fieldId: statusFieldId,
243
+ options: columns
244
+ }
245
+ });
246
+
247
+ const updateOutput = execFileSync('gh', ['api', 'graphql', '--input', '-'], { input: queryPayload }).toString().trim();
248
+ const jsonResponse = updateOutput ? JSON.parse(updateOutput) : null;
249
+ const returnedOptions = jsonResponse?.data?.updateProjectV2Field?.projectV2Field?.options || [];
250
+
251
+ for (const opt of returnedOptions) {
252
+ optionMap[opt.name] = opt.id;
253
+ }
254
+
255
+ console.log(` ${i18n.columns_ok}`);
256
+ }
257
+ } catch (err) {
258
+ console.log(` ${i18n.columns_warn}`);
259
+ }
260
+ }
261
+
262
+ console.log(`\n${yellow}${i18n.scaffolding}${reset}`);
46
263
 
47
264
  // We copy the templates folder so the agent has the real text logic to replace and rename
48
265
  const sourceTemplates = path.join(sourceDir, 'templates');
@@ -50,7 +267,33 @@ rl.question('Which AI Agent will you use for the setup? (e.g. claude, cursor, co
50
267
 
51
268
  if (fs.existsSync(sourceTemplates)) {
52
269
  copyDirSync(sourceTemplates, targetTemplates);
53
- console.log(`✅ Templates copied to .agentic-pdlc/templates/`);
270
+ console.log(`${i18n.templates_copied}`);
271
+
272
+ // Substitute values in docs/pdlc.md automatically
273
+ const pdlcDest = path.join(targetTemplates, 'docs', 'pdlc.md');
274
+ if (fs.existsSync(pdlcDest)) {
275
+ let pdlcContent = fs.readFileSync(pdlcDest, 'utf8');
276
+
277
+ if (projectId) pdlcContent = pdlcContent.replace(/\\{\\{PROJECT_ID\\}\\}/g, () => projectId);
278
+ if (statusFieldId) pdlcContent = pdlcContent.replace(/\\{\\{STATUS_FIELD_ID\\}\\}/g, () => statusFieldId);
279
+ pdlcContent = pdlcContent.replace(/\\{\\{REPO_OWNER\\}\\}/g, () => repoOwner);
280
+ pdlcContent = pdlcContent.replace(/\\{\\{REPO_NAME\\}\\}/g, () => repoName);
281
+
282
+ if (Object.keys(optionMap).length > 0) {
283
+ pdlcContent = pdlcContent.replace(/\{\{ID_IDEA\}\}/g, optionMap["💡 Idea"] || 'MISSING_ID');
284
+ pdlcContent = pdlcContent.replace(/\{\{ID_EXPLORATION\}\}/g, optionMap["🔍 Exploration"] || 'MISSING_ID');
285
+ pdlcContent = pdlcContent.replace(/\{\{ID_BRAINSTORMING\}\}/g, optionMap["🧠 Brainstorming"] || 'MISSING_ID');
286
+ pdlcContent = pdlcContent.replace(/\{\{ID_DETAIL\}\}/g, optionMap["📐 Detail Solution"] || 'MISSING_ID');
287
+ pdlcContent = pdlcContent.replace(/\{\{ID_APPROVAL\}\}/g, optionMap["✅ Approval"] || 'MISSING_ID');
288
+ pdlcContent = pdlcContent.replace(/\{\{ID_DEVELOPMENT\}\}/g, optionMap["⚙️ Development"] || 'MISSING_ID');
289
+ pdlcContent = pdlcContent.replace(/\{\{ID_TESTING\}\}/g, optionMap["🧪 Testing"] || 'MISSING_ID');
290
+ pdlcContent = pdlcContent.replace(/\{\{ID_CODE_REVIEW_PR\}\}/g, optionMap["👁 Code Review / PR"] || 'MISSING_ID');
291
+ pdlcContent = pdlcContent.replace(/\{\{ID_PRODUCTION\}\}/g, optionMap["🚀 Production"] || 'MISSING_ID');
292
+ }
293
+
294
+ fs.writeFileSync(pdlcDest, pdlcContent);
295
+ console.log(`${i18n.pdlc_prefilled}`);
296
+ }
54
297
  }
55
298
 
56
299
  // Handle the specific setup instructions target
@@ -61,15 +304,19 @@ rl.question('Which AI Agent will you use for the setup? (e.g. claude, cursor, co
61
304
  if (fs.existsSync(claudeSetupSrc)) {
62
305
  const dest = path.join(targetDir, '.agentic-setup.md');
63
306
  fs.copyFileSync(claudeSetupSrc, dest);
64
- console.log(`✅ Setup agent profile written to .agentic-setup.md`);
65
- console.log(`\n${green}🎉 Done! To start the conversational setup:${reset}`);
66
- console.log(`${cyan}\tStep 1: Open the Claude Code CLI in your terminal (type 'claude')${reset}`);
67
- console.log(`${cyan}\t [Or open your preferred IDE Agent chat, like Antigravity, Cursor, Codex, GitHub Copilot, etc]${reset}`);
68
- console.log(`${cyan}\tStep 2: Paste this exact prompt:${reset}`);
69
- console.log(`${yellow}\t "read .agentic-setup.md to enter Setup Mode."${reset}`);
70
- console.log(`\nNote: Once setup is completed, the agent will typically delete .agentic-setup.md to keep your root clean.\n`);
307
+ console.log(`${i18n.setup_written}`);
308
+ console.log(`${green}============================================================${reset}`);
309
+ console.log(`${green}${i18n.framework_scaffolded}${reset}`);
310
+ console.log(`${green}============================================================${reset}\n`);
311
+ console.log(`${yellow}${i18n.next_steps}${reset}`);
312
+ console.log(`${cyan}${i18n.step_1}${reset}`);
313
+ console.log(`${cyan}${i18n.step_2}${reset}`);
314
+ console.log(`${cyan}>>> English: "Read .agentic-setup.md and guide me through the setup."${reset}`);
315
+ console.log(`${cyan}>>> Español: "Lea el archivo .agentic-setup.md e inicie el Setup Mode"${reset}`);
316
+ console.log(`${cyan}>>> Português: "Leia o arquivo .agentic-setup.md e inicie o Setup Mode."${reset}\n`);
317
+ console.log(`${i18n.note_cleanup}`);
71
318
  } else {
72
- console.error(`❌ Could not find claude instruction file at ${claudeSetupSrc}`);
319
+ console.error(`${i18n.missing_claude}${claudeSetupSrc}`);
73
320
  }
74
321
  } else if (agent === 'cursor') {
75
322
  if (fs.existsSync(cursorSetupSrc)) {
@@ -81,22 +328,24 @@ rl.question('Which AI Agent will you use for the setup? (e.g. claude, cursor, co
81
328
  const setupPromptDest = path.join(targetDir, '.agentic-pdlc', 'SETUP_PROMPT.md');
82
329
  if (fs.existsSync(claudeSetupSrc)) fs.copyFileSync(claudeSetupSrc, setupPromptDest);
83
330
 
84
- console.log(`✅ Default cursor rules written to .cursorrules`);
85
- console.log(`✅ Framework Setup Instructions written to .agentic-pdlc/SETUP_PROMPT.md`);
86
- console.log(`\n${green}🎉 Done! To start the conversational setup:${reset}`);
87
- console.log(`${cyan}\t1. Open Cursor${reset}`);
88
- console.log(`${cyan}\t2. Open Composer (Cmd+I or Cmd+L) and type: "@.agentic-pdlc/SETUP_PROMPT.md execute Setup Mode"${reset}\n`);
331
+ console.log(`${i18n.cursor_rules_written}`);
332
+ console.log(`${i18n.cursor_setup_written}`);
333
+ console.log(`\n${green}${i18n.cursor_done}${reset}`);
334
+ console.log(`${cyan}${i18n.cursor_step_1}${reset}`);
335
+ console.log(`${cyan}${i18n.cursor_step_2}${reset}`);
89
336
  } else {
90
- console.error(`❌ Could not find cursor instruction file at ${cursorSetupSrc}`);
337
+ console.error(`${i18n.missing_claude}${cursorSetupSrc}`);
91
338
  }
92
339
  } else {
93
340
  // Generic fallback mapping
94
- const dest = path.join(targetDir, '.agentic-setup-prompt.md');
341
+ const dest = path.join(targetDir, '.agentic-setup.md');
95
342
  fs.copyFileSync(claudeSetupSrc, dest);
96
- console.log(`✅ Agent generic setup instructions written to .agentic-setup-prompt.md`);
97
- console.log(`\n${green}🎉 Done! To start the conversational setup:${reset}`);
98
- console.log(`${cyan}Provide the .agentic-setup-prompt.md file to your AI agent and ask it to execute Setup Mode!${reset}\n`);
343
+ console.log(`${i18n.generic_written}`);
344
+ console.log(`\n${green}${i18n.cursor_done}${reset}`);
345
+ console.log(`${cyan}>>> ${i18n.generic_done}${reset}`);
99
346
  }
100
347
 
101
348
  rl.close();
102
- });
349
+ }
350
+
351
+ runSetup();
package/docs/pdlc.md CHANGED
@@ -5,11 +5,11 @@
5
5
  | Column | Meaning | Who moves the card |
6
6
  |---|---|---|
7
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` |
8
+ | 🔍 Exploration | AI is analyzing code and context | Label `stage:exploration` |
9
+ | 🧠 Brainstorming | AI proposed approaches and trade-offs | Label `stage:brainstorming` |
10
+ | 📐 Detail Solution | AI is writing the technical spec | Label `stage:detailing` |
11
+ | ✅ Approval | Your turn, awaiting `spec:approved` label | Label `spec:approved` |
12
+ | ⚙️ Development | AI implementing the spec | Label `stage:development` |
13
13
  | 🧪 Testing | CI pipeline running | GitHub Actions |
14
14
  | 👁 Code Review / PR | PR opened, awaiting human review | GitHub Actions |
15
15
  | 🚀 Production | Merged | GitHub Actions |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-agentic-pdlc",
3
- "version": "2.0.3",
3
+ "version": "2.0.5",
4
4
  "description": "Agentic PDLC Framework - Conversational setup for your AI coding assistants",
5
5
  "type": "commonjs",
6
6
  "bin": {