sdd-toolkit 1.1.0 → 1.6.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.
@@ -1,9 +1,34 @@
1
+ const { TRANSLATIONS } = require('./messages');
2
+
3
+ /**
4
+ * Returns the language rule based on the locale
5
+ * @param {string} locale - 'en', 'pt-br', 'es', etc.
6
+ */
7
+ function getLanguageRule(locale = 'en') {
8
+ const normalized = locale.toLowerCase().replace('-', '_');
9
+
10
+ // Mapping locale slug to property key in messages
11
+ const keyMap = {
12
+ 'en': 'EN',
13
+ 'pt_br': 'PT_BR',
14
+ 'es': 'ES'
15
+ };
16
+
17
+ const ruleKey = keyMap[normalized] || 'EN';
18
+
19
+ // Get dictionary for the target locale or fallback to EN
20
+ const dict = TRANSLATIONS[normalized] || TRANSLATIONS['en'];
21
+
22
+ return dict.LANGUAGE_RULES[ruleKey];
23
+ }
24
+
1
25
  /**
2
26
  * Converte definição do agente para TOML do Gemini CLI
3
27
  */
4
- function toGeminiTOML(agent) {
28
+ function toGeminiTOML(agent, options = {}) {
29
+ const languageRule = getLanguageRule(options.locale);
5
30
  // Escapa aspas duplas na descrição
6
- const description = (agent.description || agent.role).replace(/"/g, '\\"');
31
+ const description = (agent.description || agent.role).replace(/"/g, '\"');
7
32
 
8
33
  // Constrói o prompt completo
9
34
  const parts = [
@@ -15,26 +40,28 @@ function toGeminiTOML(agent) {
15
40
  '\n'
16
41
  ];
17
42
 
18
- if (agent.rules && agent.rules.length > 0) {
43
+ const allRules = [languageRule, ...(agent.rules || [])];
44
+
45
+ if (allRules.length > 0) {
19
46
  parts.push(`# Rules & Guidelines`);
20
- agent.rules.forEach(rule => parts.push(`- ${rule}`));
47
+ allRules.forEach(rule => parts.push(`- ${rule}`));
21
48
  parts.push('\n');
22
49
  }
23
50
 
24
51
  const fullPrompt = parts.join('\n');
25
52
 
26
53
  // Escapa aspas triplas para o bloco multilinha TOML
27
- const escapedPrompt = fullPrompt.replace(/"""/g, '\\"\\\"\\"');
54
+ const escapedPrompt = fullPrompt.replace(/"""/g, '\"\"\"');
28
55
 
29
56
  // Monta o TOML final
30
57
  let toml = `description = "${description}"\n`;
31
58
  toml += `prompt = """\n${escapedPrompt}\n"""\n`;
32
59
 
33
60
  // Mantém rules como array separado se a ferramenta suportar (Gemini CLI suporta)
34
- if (agent.rules && agent.rules.length > 0) {
61
+ if (allRules.length > 0) {
35
62
  toml += 'rules = [\n';
36
- agent.rules.forEach(rule => {
37
- const escaped = rule.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
63
+ allRules.forEach(rule => {
64
+ const escaped = rule.replace(/\\/g, '\\\\').replace(/"/g, '\"');
38
65
  toml += ` "${escaped}",\n`;
39
66
  });
40
67
  toml += ']\n';
@@ -46,15 +73,18 @@ function toGeminiTOML(agent) {
46
73
  /**
47
74
  * Converte para configuração de Custom Mode do Roo Code / Cline (JSON)
48
75
  */
49
- function toRooConfig(agent, slug) {
76
+ function toRooConfig(agent, slug, options = {}) {
77
+ const languageRule = getLanguageRule(options.locale);
50
78
  const promptParts = [
51
79
  `# ${agent.name} (${agent.role})`,
52
80
  `\n${agent.systemPrompt.trim()}\n`
53
81
  ];
54
82
 
55
- if (agent.rules && agent.rules.length > 0) {
83
+ const allRules = [languageRule, ...(agent.rules || [])];
84
+
85
+ if (allRules.length > 0) {
56
86
  promptParts.push(`## Rules & Guidelines`);
57
- agent.rules.forEach(rule => promptParts.push(`- ${rule}`));
87
+ allRules.forEach(rule => promptParts.push(`- ${rule}`));
58
88
  }
59
89
 
60
90
  return {
@@ -68,7 +98,8 @@ function toRooConfig(agent, slug) {
68
98
  /**
69
99
  * Converte para Markdown do Kilo Code
70
100
  */
71
- function toKiloMarkdown(agent) {
101
+ function toKiloMarkdown(agent, options = {}) {
102
+ const languageRule = getLanguageRule(options.locale);
72
103
  const parts = [
73
104
  `<!--- Kilo Code Agent Config --->`,
74
105
  `# ${agent.name} ${agent.emoji}`,
@@ -78,9 +109,11 @@ function toKiloMarkdown(agent) {
78
109
  '\n'
79
110
  ];
80
111
 
81
- if (agent.rules && agent.rules.length > 0) {
112
+ const allRules = [languageRule, ...(agent.rules || [])];
113
+
114
+ if (allRules.length > 0) {
82
115
  parts.push(`## Constraints`);
83
- agent.rules.forEach(rule => parts.push(`- ${rule}`));
116
+ allRules.forEach(rule => parts.push(`- ${rule}`));
84
117
  }
85
118
 
86
119
  return parts.join('\n');
@@ -89,7 +122,8 @@ function toKiloMarkdown(agent) {
89
122
  /**
90
123
  * Converte para Instruções do GitHub Copilot (.github/copilot-instructions.md)
91
124
  */
92
- function toCopilotInstructions(agent) {
125
+ function toCopilotInstructions(agent, options = {}) {
126
+ const languageRule = getLanguageRule(options.locale);
93
127
  const parts = [
94
128
  `<!-- GitHub Copilot Instructions for ${agent.name} -->`,
95
129
  `# Identity and Role`,
@@ -100,15 +134,16 @@ function toCopilotInstructions(agent) {
100
134
  '\n'
101
135
  ];
102
136
 
103
- if (agent.rules && agent.rules.length > 0) {
137
+ const allRules = [languageRule, ...(agent.rules || [])];
138
+
139
+ if (allRules.length > 0) {
104
140
  parts.push(`## Rules & Guidelines`);
105
- agent.rules.forEach(rule => parts.push(`- ${rule}`));
141
+ allRules.forEach(rule => parts.push(`- ${rule}`));
106
142
  }
107
143
 
108
144
  // Adiciona uma seção de estilo de resposta para garantir conformidade
109
145
  parts.push(`\n## Response Style`);
110
146
  parts.push(`- Be concise and objective.`);
111
- parts.push(`- Use Portuguese (Brazil) unless told otherwise.`);
112
147
  parts.push(`- Follow the project conventions defined in the workspace.`);
113
148
 
114
149
  return parts.join('\n');
@@ -118,7 +153,8 @@ function toCopilotInstructions(agent) {
118
153
  * Converte para Cursor Rules (.mdc)
119
154
  * Inclui Frontmatter para Contexto
120
155
  */
121
- function toCursorMDC(agent) {
156
+ function toCursorMDC(agent, options = {}) {
157
+ const languageRule = getLanguageRule(options.locale);
122
158
  // Tenta inferir globs baseados no papel do agente
123
159
  let globs = "*";
124
160
  const roleLower = agent.slug.toLowerCase();
@@ -127,7 +163,9 @@ function toCursorMDC(agent) {
127
163
  if (roleLower.includes('css') || roleLower.includes('style')) globs = "*.css, *.scss, *.tailwind";
128
164
  if (roleLower.includes('sql') || roleLower.includes('db')) globs = "*.sql, *.prisma, *.schema";
129
165
 
130
- return `---
166
+ const allRules = [languageRule, ...(agent.rules || [])];
167
+
168
+ return `---
131
169
  description: ${agent.description || agent.role}
132
170
  globs: ${globs}
133
171
  ---
@@ -138,14 +176,18 @@ Role: ${agent.role}
138
176
  ## Instructions
139
177
  ${agent.systemPrompt.trim()}
140
178
 
141
- ${agent.rules && agent.rules.length > 0 ? '## Rules\n' + agent.rules.map(r => `- ${r}`).join('\n') : ''}
179
+ ${allRules.length > 0 ? '## Rules\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
142
180
  `;
143
181
  }
144
182
 
145
183
  /**
146
- * Converte para Windsurf (.windsurfrules)
184
+ * Converte para Windsurf Workflow (.windsurf/workflows/*.md)
185
+ * Cascade reconhece esses arquivos como comandos de workflow
147
186
  */
148
- function toWindsurfRules(agent) {
187
+ function toWindsurfRules(agent, options = {}) {
188
+ const languageRule = getLanguageRule(options.locale);
189
+ const allRules = [languageRule, ...(agent.rules || [])];
190
+
149
191
  return `# ${agent.name} ${agent.emoji} Rules
150
192
 
151
193
  Role: ${agent.role}
@@ -153,28 +195,117 @@ Role: ${agent.role}
153
195
  ## Core Logic
154
196
  ${agent.systemPrompt.trim()}
155
197
 
156
- ${agent.rules && agent.rules.length > 0 ? '## Guidelines\n' + agent.rules.map(r => `- ${r}`).join('\n') : ''}
198
+ ${allRules.length > 0 ? '## Guidelines\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
199
+ `;
200
+ }
201
+
202
+ /**
203
+ * Converte para Claude Code Command (.claude/commands/openspec/*.md)
204
+ */
205
+ function toClaudeCommand(agent, options = {}) {
206
+ const languageRule = getLanguageRule(options.locale);
207
+ const allRules = [languageRule, ...(agent.rules || [])];
208
+
209
+ return `---
210
+ name: OpenSpec: ${agent.name}
211
+ description: ${agent.description || agent.role}
212
+ category: OpenSpec
213
+ ---
214
+ # ${agent.name} ${agent.emoji}
215
+
216
+ Role: ${agent.role}
217
+
218
+ ## Instructions
219
+ ${agent.systemPrompt.trim()}
220
+
221
+ ${allRules.length > 0 ? '## Rules\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
157
222
  `;
158
223
  }
159
224
 
160
225
  /**
161
226
  * Converte para System Prompt Puro (OpenAI/Claude/Web)
162
227
  */
163
- function toPlainSystemPrompt(agent) {
228
+ function toPlainSystemPrompt(agent, options = {}) {
229
+ const languageRule = getLanguageRule(options.locale);
230
+ const allRules = [languageRule, ...(agent.rules || [])];
231
+
164
232
  return `You are ${agent.name} ${agent.emoji}
165
233
  Role: ${agent.role}
166
234
 
167
235
  [SYSTEM INSTRUCTIONS]
168
236
  ${agent.systemPrompt.trim()}
169
237
 
170
- ${agent.rules && agent.rules.length > 0 ? '[GUIDELINES]\n' + agent.rules.map(r => `- ${r}`).join('\n') : ''}
238
+ ${allRules.length > 0 ? '[GUIDELINES]\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
171
239
  `;
172
240
  }
173
241
 
174
242
  /**
175
243
  * Converte para Trae Instructions
176
244
  */
177
- function toTraeRules(agent) {
245
+ function toTraeRules(agent, options = {}) {
246
+ const languageRule = getLanguageRule(options.locale);
247
+ const allRules = [languageRule, ...(agent.rules || [])];
248
+
249
+ return `<!-- Trae Workspace Rules -->
250
+ # ${agent.name} ${agent.emoji}
251
+
252
+ **Role**: ${agent.role}
253
+
254
+ ## Context & Instructions
255
+ ${agent.systemPrompt.trim()}
256
+
257
+ ${allRules.length > 0 ? '## Constraints\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
258
+ `;
259
+ }
260
+
261
+ /**
262
+ * Converte para OpenCode Agent (.opencode/agent/*.md)
263
+ */
264
+ function toOpenCodeAgent(agent, options = {}) {
265
+ const languageRule = getLanguageRule(options.locale);
266
+ const allRules = [languageRule, ...(agent.rules || [])];
267
+
268
+ // Configurar permissões baseado no tipo de agente
269
+ const isReadOnly = agent.slug.includes('review') || agent.slug.includes('audit') || agent.name.includes('Architect') || agent.role.includes('QA') || agent.role.includes('Review');
270
+ const tools = {
271
+ write: !isReadOnly,
272
+ edit: !isReadOnly,
273
+ bash: !isReadOnly
274
+ };
275
+
276
+ const frontmatter = {
277
+ description: agent.description || agent.role,
278
+ mode: 'subagent',
279
+ temperature: 0.3,
280
+ tools
281
+ };
282
+
283
+ const frontmatterStr = Object.entries(frontmatter)
284
+ .map(([key, value]) => `${key}: ${JSON.stringify(value)}`)
285
+ .join('\n');
286
+
287
+ return `---
288
+ ${frontmatterStr}
289
+ ---
290
+
291
+ # ${agent.name} ${agent.emoji}
292
+
293
+ **Role**: ${agent.role}
294
+
295
+ ${agent.systemPrompt.trim()}
296
+
297
+ ## Rules
298
+ ${allRules.map(rule => `- ${rule}`).join('\n')}
299
+ `;
300
+ }
301
+
302
+ /**
303
+ * Converte para Trae Instructions
304
+ */
305
+ function toTraeRules(agent, options = {}) {
306
+ const languageRule = getLanguageRule(options.locale);
307
+ const allRules = [languageRule, ...(agent.rules || [])];
308
+
178
309
  return `<!-- Trae Workspace Rules -->
179
310
  # ${agent.name} ${agent.emoji}
180
311
 
@@ -183,17 +314,19 @@ function toTraeRules(agent) {
183
314
  ## Context & Instructions
184
315
  ${agent.systemPrompt.trim()}
185
316
 
186
- ${agent.rules && agent.rules.length > 0 ? '## Constraints\n' + agent.rules.map(r => `- ${r}`).join('\n') : ''}
317
+ ${allRules.length > 0 ? '## Constraints\n' + allRules.map(r => `- ${r}`).join('\n') : ''}
187
318
  `;
188
319
  }
189
320
 
190
- module.exports = {
191
- toGeminiTOML,
192
- toRooConfig,
193
- toKiloMarkdown,
321
+ module.exports = {
322
+ toGeminiTOML,
323
+ toRooConfig,
324
+ toKiloMarkdown,
194
325
  toCopilotInstructions,
195
326
  toCursorMDC,
196
327
  toWindsurfRules,
328
+ toClaudeCommand,
197
329
  toPlainSystemPrompt,
198
- toTraeRules
330
+ toTraeRules,
331
+ toOpenCodeAgent
199
332
  };
@@ -0,0 +1,56 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const readline = require('readline');
4
+
5
+ const docsDir = path.join(process.cwd(), '.sdd-toolkit');
6
+ const archiveDir = path.join(docsDir, 'archive');
7
+
8
+ // Files to archive (Ephemeral context)
9
+ const filesToArchive = ['project.md', 'task.md', 'audit_report.md', 'requirements.md', 'milestones.md'];
10
+
11
+ // Files to keep (Long-term context)
12
+ // - guidelines.md (Laws)
13
+ // - context.md (Project Reality)
14
+ // - work_log.md (History)
15
+
16
+ const rl = readline.createInterface({
17
+ input: process.stdin,
18
+ output: process.stdout
19
+ });
20
+
21
+ console.log('📦 SDD SESSION ARCHIVER');
22
+ console.log('This will move current Spec, Plan, and Audit reports to .sdd-toolkit/archive/.');
23
+ console.log('Your Work Log and Context will remain untouched.\n');
24
+
25
+ // Check if there is anything to archive
26
+ const existingFiles = filesToArchive.filter(f => fs.existsSync(path.join(docsDir, f)));
27
+
28
+ if (existingFiles.length === 0) {
29
+ console.log('❌ No active session files found (spec.md, plan.md, etc). Nothing to archive.');
30
+ process.exit(0);
31
+ }
32
+
33
+ rl.question('Enter a name for this feature/session (e.g., "auth-system"): ', (name) => {
34
+ const safeName = (name || 'untitled').replace(/[^a-z0-9-_]/gi, '-').toLowerCase();
35
+ const timestamp = new Date().toISOString().split('T')[0];
36
+ const folderName = `${timestamp}_${safeName}`;
37
+ const targetDir = path.join(archiveDir, folderName);
38
+
39
+ if (!fs.existsSync(targetDir)) {
40
+ fs.mkdirSync(targetDir, { recursive: true });
41
+ }
42
+
43
+ console.log(`\nMoving files to: .sdd-toolkit/archive/${folderName}/
44
+ `);
45
+
46
+ existingFiles.forEach(file => {
47
+ const srcPath = path.join(docsDir, file);
48
+ const destPath = path.join(targetDir, file);
49
+ fs.renameSync(srcPath, destPath);
50
+ console.log(`✔ Archived: ${file}`);
51
+ });
52
+
53
+ console.log('\n✅ Session archived successfully!');
54
+ console.log('You are ready to start a new feature with /spec');
55
+ rl.close();
56
+ });
@@ -0,0 +1,19 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const docsDir = path.join(process.cwd(), '.sdd-toolkit');
5
+
6
+ console.log('⚠️ WARNING: This will wipe all documentation (Spec, Plan, Context).');
7
+ console.log('Your source code (src/) will NOT be touched.');
8
+ console.log('Are you sure? (Run with --force to execute)');
9
+
10
+ if (process.argv.includes('--force')) {
11
+ ['project.md', 'task.md', 'requirements.md', 'milestones.md', 'guidelines.md', 'audit_report.md'].forEach(file => {
12
+ const p = path.join(docsDir, file);
13
+ if (fs.existsSync(p)) {
14
+ fs.unlinkSync(p);
15
+ console.log(`Deleted: .sdd-toolkit/${file}`);
16
+ }
17
+ });
18
+ console.log('✅ Wipe complete. You can start fresh with /explore');
19
+ }
@@ -0,0 +1,58 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ // Tenta carregar picocolors se estiver disponível no projeto do usuário, senão usa fallback
5
+ let pc = {
6
+ green: s => s,
7
+ blue: s => s,
8
+ yellow: s => s,
9
+ red: s => s,
10
+ bold: s => s,
11
+ bgBlue: s => s
12
+ };
13
+ try { pc = require('picocolors'); } catch (e) {}
14
+
15
+ const docsDir = path.join(process.cwd(), '.sdd-toolkit');
16
+
17
+ function checkFile(name) {
18
+ const p = path.join(docsDir, name);
19
+ if (fs.existsSync(p)) {
20
+ const stats = fs.statSync(p);
21
+ return { exists: true, size: stats.size, mtime: stats.mtime };
22
+ }
23
+ return { exists: false };
24
+ }
25
+
26
+ console.clear();
27
+ console.log(pc.bgBlue(pc.bold(' 📊 SDD PROJECT STATUS ')));
28
+ console.log('');
29
+
30
+ // 1. Spec Status
31
+ const spec = checkFile('project.md');
32
+ if (spec.exists && spec.size > 100) {
33
+ console.log(`${pc.green('✔ Spec Defined')} (Last update: ${spec.mtime.toLocaleString()})`);
34
+ } else {
35
+ console.log(`${pc.red('✖ Spec Missing')} (Run /project)`);
36
+ }
37
+
38
+ // 2. Plan Status
39
+ const plan = checkFile('task.md');
40
+ if (plan.exists && plan.size > 100) {
41
+ console.log(`${pc.green('✔ Plan Active')} (Last update: ${plan.mtime.toLocaleString()})`);
42
+
43
+ // Tenta ler progresso simples
44
+ try {
45
+ const content = fs.readFileSync(path.join(docsDir, 'task.md'), 'utf-8');
46
+ const total = (content.match(/- \[ \]/g) || []).length + (content.match(/- \[x\]/g) || []).length;
47
+ const done = (content.match(/- \[x\]/g) || []).length;
48
+ if (total > 0) {
49
+ const percent = Math.round((done / total) * 100);
50
+ console.log(` Progress: [${'#'.repeat(Math.floor(percent/10))}${'-'.repeat(10 - Math.floor(percent/10))}] ${percent}% (${done}/${total} tasks)`);
51
+ }
52
+ } catch (e) {}
53
+ } else {
54
+ console.log(`${pc.yellow('⚠ Plan Missing')} (Run /tasks)`);
55
+ }
56
+
57
+ console.log('');
58
+ console.log('Use /build to continue work.');
@@ -0,0 +1,9 @@
1
+ # 📜 Project Guidelines
2
+
3
+ ## 🏗️ Architecture Patterns
4
+
5
+ ## 💻 Code Conventions
6
+
7
+ ## 🛠️ Tech Stack & Versions
8
+
9
+ ## 🛡️ Security & Performance
@@ -0,0 +1,14 @@
1
+ ---
2
+ title: Development Roadmap
3
+ source_spec: .sdd-toolkit/project.md
4
+ last_updated:
5
+ status:
6
+ ---
7
+
8
+ # Strategic Roadmap
9
+
10
+ ## 1. Strategy Summary
11
+
12
+ ## 2. Milestones Detail
13
+
14
+ ## 3. Risk Matrix
@@ -0,0 +1,28 @@
1
+ ---
2
+ title:
3
+ version:
4
+ status:
5
+ last_updated:
6
+ ---
7
+
8
+ #
9
+
10
+ ## 1. Overview
11
+
12
+ ## 2. Business Objectives
13
+
14
+ ## 3. Actors and Personas
15
+
16
+ ## 4. Modules and Features Structure
17
+
18
+ ## 5. User Journey (Flow)
19
+
20
+ ## 6. Business Rules
21
+
22
+ ## 7. External Integrations
23
+
24
+ ## 8. Non-Functional Requirements & Constraints
25
+
26
+ ## 9. Data Definitions
27
+
28
+ ## 10. Project Principles (Constitution)
@@ -0,0 +1,15 @@
1
+ ---
2
+ title: Requirements and Architecture Specification
3
+ scope:
4
+ last_updated:
5
+ ---
6
+
7
+ # Requirements and Stack Catalog
8
+
9
+ ## 1. Tech Stack and Standards (Tech Constraints)
10
+
11
+ ## 2. Functional Requirements (FR)
12
+
13
+ ## 3. Non-Functional Requirements (NFR)
14
+
15
+ ## 4. Data Model (Schema Draft)
@@ -0,0 +1,11 @@
1
+ ---
2
+ title: Tasks Sprint -
3
+ milestone_ref:
4
+ tech_stack:
5
+ ---
6
+
7
+ # Execution Backlog:
8
+
9
+ ## Technical Summary
10
+
11
+ ## Tasks Checklist
@@ -1,54 +0,0 @@
1
- name: Auditor
2
- role: Blueprint Validator & Consistency Checker
3
- emoji: 🕵️
4
- systemPrompt: |
5
- # SYSTEM ROLE & IDENTITY
6
- You are the **Lead Auditor**.
7
- Your role is to **prevent failure** by detecting gaps in planning BEFORE code is written.
8
- You do not execute code. You analyze logical consistency between documents.
9
-
10
- # INPUT CONTEXT
11
- 1. **Mandatory Reading:**
12
- - `docs/requirements.md` (The Contract).
13
- - `docs/task.md` (The Plan).
14
- - `docs/milestones.md` (The Strategy).
15
-
16
- # WORKFLOW (AUDIT PROCESS)
17
- Execute a non-destructive analysis to verify if the Plan covers the Contract.
18
-
19
- ## 1. Coverage Analysis
20
- - Map every Requirement (FR-XX, BR-XX) to at least one Task (M1-TXX).
21
- - **FLAG** any orphaned requirement (exists in docs but no task to implement it).
22
-
23
- ## 2. Ambiguity Detection
24
- - Scan `task.md` for vague terms: "Make it work", "Fix bugs", "improve".
25
- - **Task Definition:** Every task MUST have a clear "DoD" (Definition of Done) or "Acceptance Criteria".
26
-
27
- ## 3. Conflict Check
28
- - Check if `task.md` contradicts `requirements.md` (e.g., Req says "Postgres", Task says "Install Mongo").
29
-
30
- # OUTPUT STRUCTURE (docs/logs/audit_report.md)
31
-
32
- ---
33
- **Audit Date:** [YYYY-MM-DD HH:MM]
34
- **Status:** [PASS / WARN / FAIL]
35
-
36
- ## 1. Coverage Matrix
37
- - [x] FR-01 -> M1-T02
38
- - [ ] FR-02 -> **MISSING IN TASKS** (Critical)
39
-
40
- ## 2. Issues Found
41
- - **Critical:** Requirement [FR-02] has no implementation task.
42
- - **Warning:** Task [M1-T04] mentions "Optimize" without specific metric.
43
-
44
- ## 3. Recommendation
45
- - [ ] Generate detailed tasks for FR-02.
46
- - [ ] Proceed to code (only if Status is PASS).
47
- ---
48
-
49
- # INSTRUCTION
50
- Read requirements and tasks. Generate the `audit_report.md`.
51
- rules:
52
- - "**STRICTNESS:** If a Business Rule (BR) is ignored, Fail the audit."
53
- - "**NO ASSUMPTIONS:** If a task suggests a library not in requirements, Flag it."
54
- - "Language Adaptability: Respond in English by default. If the user speaks in another language, mirror their language."