@girardelli/architect 2.2.0 → 4.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.
Files changed (296) hide show
  1. package/README.md +105 -116
  2. package/__test_agent_output__/INDEX.md +1 -0
  3. package/__test_agent_output__/agents/AGENT-ORCHESTRATOR.md +1 -0
  4. package/__test_agent_output__/agents/DATABASE-ENGINEER.md +174 -0
  5. package/__test_agent_output__/agents/QA-TEST-ENGINEER.md +138 -0
  6. package/__test_agent_output__/agents/SECURITY-AUDITOR.md +106 -0
  7. package/__test_agent_output__/agents/TECH-DEBT-CONTROLLER.md +104 -0
  8. package/__test_agent_output__/agents/TYPESCRIPT-BACKEND-DEVELOPER.md +135 -0
  9. package/__test_agent_output__/guards/CODE-REVIEW-CHECKLIST.md +95 -0
  10. package/__test_agent_output__/guards/PREFLIGHT.md +200 -0
  11. package/__test_agent_output__/guards/QUALITY-GATES.md +1 -0
  12. package/__test_agent_output__/rules/00-general.md +229 -0
  13. package/__test_agent_output__/rules/01-architecture.md +191 -0
  14. package/__test_agent_output__/rules/02-security.md +402 -0
  15. package/__test_agent_output__/rules/03-nestjs.md +124 -0
  16. package/__test_agent_output__/templates/ADR.md +95 -0
  17. package/__test_agent_output__/templates/BDD.md +58 -0
  18. package/__test_agent_output__/templates/C4.md +68 -0
  19. package/__test_agent_output__/templates/TDD.md +86 -0
  20. package/__test_agent_output__/templates/THREAT-MODEL.md +82 -0
  21. package/__test_agent_output__/workflows/fix-bug.md +228 -0
  22. package/__test_agent_output__/workflows/new-feature.md +311 -0
  23. package/__test_agent_output__/workflows/review.md +95 -0
  24. package/__test_context_7RvUrO/src/modules/empty/empty.ts +0 -0
  25. package/__test_context_Rf5fNJ/src/modules/mixed/mixed.ts +5 -0
  26. package/__test_context_WRCnYH/src/modules/test/test.ts +10 -0
  27. package/__test_context_YsnVS3/src/modules/test/test.ts +10 -0
  28. package/__test_context_w7XZeH/src/modules/mixed/mixed.ts +5 -0
  29. package/__test_context_y5noh6/src/modules/empty/empty.ts +0 -0
  30. package/__test_framework__24OjAu/package.json +1 -0
  31. package/__test_framework__3ZDZsx/pyproject.toml +8 -0
  32. package/__test_framework__4T54Jn/package.json +1 -0
  33. package/__test_framework__4tlXu9/pyproject.toml +8 -0
  34. package/__test_framework__6boWqQ/Pipfile +6 -0
  35. package/__test_framework__6gygMU/pom.xml +10 -0
  36. package/__test_framework__6kxj0N/go.mod +8 -0
  37. package/__test_framework__7CEoXw/pom.xml +10 -0
  38. package/__test_framework__85DDz0/Pipfile +6 -0
  39. package/__test_framework__9WrRIr/pom.xml +7 -0
  40. package/__test_framework__ANqGKl/Gemfile +5 -0
  41. package/__test_framework__BCXTEM/go.mod +3 -0
  42. package/__test_framework__BHiPNq/setup.py +2 -0
  43. package/__test_framework__BqkiKv/package.json +1 -0
  44. package/__test_framework__C5yd8X/Pipfile.lock +1 -0
  45. package/__test_framework__C5yd8X/requirements.txt +1 -0
  46. package/__test_framework__C87d3a/manage.py +1 -0
  47. package/__test_framework__C87d3a/requirements.txt +2 -0
  48. package/__test_framework__DXNwc5/build.gradle +7 -0
  49. package/__test_framework__GhHSt3/build.gradle.kts +4 -0
  50. package/__test_framework__GzklJP/Cargo.toml +7 -0
  51. package/__test_framework__H4hd13/go.mod +8 -0
  52. package/__test_framework__HKjOXO/composer.json +1 -0
  53. package/__test_framework__HaDN45/Gemfile +3 -0
  54. package/__test_framework__IBO7YG/pyproject.toml +9 -0
  55. package/__test_framework__JwSOyF/pyproject.toml +6 -0
  56. package/__test_framework__K6HrCr/build.gradle +2 -0
  57. package/__test_framework__KzRPlh/pubspec.yaml +9 -0
  58. package/__test_framework__L6uIym/pyproject.toml +6 -0
  59. package/__test_framework__LOdoGK/requirements.txt +4 -0
  60. package/__test_framework__LgHzss/package.json +1 -0
  61. package/__test_framework__M76M6q/Gemfile +5 -0
  62. package/__test_framework__Mr9vWW/composer.json +1 -0
  63. package/__test_framework__N03Gnv/package.json +1 -0
  64. package/__test_framework__Num4UE/requirements +1 -0
  65. package/__test_framework__OAGw3Y/build.gradle +7 -0
  66. package/__test_framework__OQc8yG/pubspec.yaml +9 -0
  67. package/__test_framework__OwKZcd/requirements.txt +3 -0
  68. package/__test_framework__P0gFv7/requirements +1 -0
  69. package/__test_framework__PN55Rq/package.json +1 -0
  70. package/__test_framework__PQiqX8/pubspec.yaml +3 -0
  71. package/__test_framework__RBHsg7/composer.json +1 -0
  72. package/__test_framework__RHxif4/Cargo.toml +7 -0
  73. package/__test_framework__T0v0p1/Cargo.toml +4 -0
  74. package/__test_framework__Tu0clt/Pipfile.lock +1 -0
  75. package/__test_framework__Tu0clt/requirements.txt +1 -0
  76. package/__test_framework__TwDj9P/Cargo.toml +4 -0
  77. package/__test_framework__VQJNC4/pom.xml +7 -0
  78. package/__test_framework__W6sm05/package.json +1 -0
  79. package/__test_framework__W7vBLy/pyproject.toml +4 -0
  80. package/__test_framework__WNJOWT/setup.py +2 -0
  81. package/__test_framework__WSJs7U/package.json +1 -0
  82. package/__test_framework__YQ5VpA/build.gradle.kts +4 -0
  83. package/__test_framework__ZNEUEs/package.json +1 -0
  84. package/__test_framework__Znt922/pom.xml +7 -0
  85. package/__test_framework__azyg0h/pom.xml +7 -0
  86. package/__test_framework__c6otLr/package.json +1 -0
  87. package/__test_framework__cl9S9G/build.gradle +2 -0
  88. package/__test_framework__eilvV4/composer.json +1 -0
  89. package/__test_framework__gQZxXO/manage.py +1 -0
  90. package/__test_framework__gQZxXO/requirements.txt +2 -0
  91. package/__test_framework__ghvl26/poetry.lock +1 -0
  92. package/__test_framework__ghvl26/pyproject.toml +2 -0
  93. package/__test_framework__hR7b9U/Makefile +11 -0
  94. package/__test_framework__iESVsi/composer.json +1 -0
  95. package/__test_framework__jm6TJy/package.json +1 -0
  96. package/__test_framework__kBUpjs/pyproject.toml +9 -0
  97. package/__test_framework__kqoZrw/requirements.txt +4 -0
  98. package/__test_framework__lWkoyO/pyproject.toml +4 -0
  99. package/__test_framework__mTKnUO/package.json +1 -0
  100. package/__test_framework__nCeZwe/Makefile +11 -0
  101. package/__test_framework__oljsU0/package.json +1 -0
  102. package/__test_framework__osRG4q/go.mod +3 -0
  103. package/__test_framework__pCHH4F/package.json +1 -0
  104. package/__test_framework__pExx6E/Gemfile +3 -0
  105. package/__test_framework__pyBoGd/pyproject.toml +5 -0
  106. package/__test_framework__qw16VQ/package.json +1 -0
  107. package/__test_framework__rRayrG/package.json +1 -0
  108. package/__test_framework__s82zO5/package.json +1 -0
  109. package/__test_framework__tp8MFK/pyproject.toml +5 -0
  110. package/__test_framework__w44k4w/composer.json +1 -0
  111. package/__test_framework__yefPZY/poetry.lock +1 -0
  112. package/__test_framework__yefPZY/pyproject.toml +2 -0
  113. package/__test_framework__zCiyDT/requirements.txt +3 -0
  114. package/__test_framework__zGZN3j/pubspec.yaml +3 -0
  115. package/__test_framework__zXpnxL/package.json +1 -0
  116. package/architect-run.sh +431 -0
  117. package/assets/banner-v3.html +561 -0
  118. package/dist/agent-generator/context-enricher.d.ts +58 -0
  119. package/dist/agent-generator/context-enricher.d.ts.map +1 -0
  120. package/dist/agent-generator/context-enricher.js +581 -0
  121. package/dist/agent-generator/context-enricher.js.map +1 -0
  122. package/dist/agent-generator/domain-inferrer.d.ts +52 -0
  123. package/dist/agent-generator/domain-inferrer.d.ts.map +1 -0
  124. package/dist/agent-generator/domain-inferrer.js +575 -0
  125. package/dist/agent-generator/domain-inferrer.js.map +1 -0
  126. package/dist/agent-generator/framework-detector.d.ts +40 -0
  127. package/dist/agent-generator/framework-detector.d.ts.map +1 -0
  128. package/dist/agent-generator/framework-detector.js +611 -0
  129. package/dist/agent-generator/framework-detector.js.map +1 -0
  130. package/dist/agent-generator/index.d.ts +33 -0
  131. package/dist/agent-generator/index.d.ts.map +1 -0
  132. package/dist/agent-generator/index.js +477 -0
  133. package/dist/agent-generator/index.js.map +1 -0
  134. package/dist/agent-generator/stack-detector.d.ts +12 -0
  135. package/dist/agent-generator/stack-detector.d.ts.map +1 -0
  136. package/dist/agent-generator/stack-detector.js +128 -0
  137. package/dist/agent-generator/stack-detector.js.map +1 -0
  138. package/dist/agent-generator/templates/core/agents.d.ts +17 -0
  139. package/dist/agent-generator/templates/core/agents.d.ts.map +1 -0
  140. package/dist/agent-generator/templates/core/agents.js +1252 -0
  141. package/dist/agent-generator/templates/core/agents.js.map +1 -0
  142. package/dist/agent-generator/templates/core/architecture-rules.d.ts +7 -0
  143. package/dist/agent-generator/templates/core/architecture-rules.d.ts.map +1 -0
  144. package/dist/agent-generator/templates/core/architecture-rules.js +274 -0
  145. package/dist/agent-generator/templates/core/architecture-rules.js.map +1 -0
  146. package/dist/agent-generator/templates/core/general-rules.d.ts +8 -0
  147. package/dist/agent-generator/templates/core/general-rules.d.ts.map +1 -0
  148. package/dist/agent-generator/templates/core/general-rules.js +301 -0
  149. package/dist/agent-generator/templates/core/general-rules.js.map +1 -0
  150. package/dist/agent-generator/templates/core/index-md.d.ts +7 -0
  151. package/dist/agent-generator/templates/core/index-md.d.ts.map +1 -0
  152. package/dist/agent-generator/templates/core/index-md.js +246 -0
  153. package/dist/agent-generator/templates/core/index-md.js.map +1 -0
  154. package/dist/agent-generator/templates/core/orchestrator.d.ts +8 -0
  155. package/dist/agent-generator/templates/core/orchestrator.d.ts.map +1 -0
  156. package/dist/agent-generator/templates/core/orchestrator.js +422 -0
  157. package/dist/agent-generator/templates/core/orchestrator.js.map +1 -0
  158. package/dist/agent-generator/templates/core/preflight.d.ts +8 -0
  159. package/dist/agent-generator/templates/core/preflight.d.ts.map +1 -0
  160. package/dist/agent-generator/templates/core/preflight.js +213 -0
  161. package/dist/agent-generator/templates/core/preflight.js.map +1 -0
  162. package/dist/agent-generator/templates/core/quality-gates.d.ts +11 -0
  163. package/dist/agent-generator/templates/core/quality-gates.d.ts.map +1 -0
  164. package/dist/agent-generator/templates/core/quality-gates.js +254 -0
  165. package/dist/agent-generator/templates/core/quality-gates.js.map +1 -0
  166. package/dist/agent-generator/templates/core/security-rules.d.ts +7 -0
  167. package/dist/agent-generator/templates/core/security-rules.d.ts.map +1 -0
  168. package/dist/agent-generator/templates/core/security-rules.js +528 -0
  169. package/dist/agent-generator/templates/core/security-rules.js.map +1 -0
  170. package/dist/agent-generator/templates/core/skills-generator.d.ts +6 -0
  171. package/dist/agent-generator/templates/core/skills-generator.d.ts.map +1 -0
  172. package/dist/agent-generator/templates/core/skills-generator.js +207 -0
  173. package/dist/agent-generator/templates/core/skills-generator.js.map +1 -0
  174. package/dist/agent-generator/templates/core/workflow-fix-bug.d.ts +7 -0
  175. package/dist/agent-generator/templates/core/workflow-fix-bug.d.ts.map +1 -0
  176. package/dist/agent-generator/templates/core/workflow-fix-bug.js +237 -0
  177. package/dist/agent-generator/templates/core/workflow-fix-bug.js.map +1 -0
  178. package/dist/agent-generator/templates/core/workflow-new-feature.d.ts +8 -0
  179. package/dist/agent-generator/templates/core/workflow-new-feature.d.ts.map +1 -0
  180. package/dist/agent-generator/templates/core/workflow-new-feature.js +321 -0
  181. package/dist/agent-generator/templates/core/workflow-new-feature.js.map +1 -0
  182. package/dist/agent-generator/templates/core/workflow-review.d.ts +7 -0
  183. package/dist/agent-generator/templates/core/workflow-review.d.ts.map +1 -0
  184. package/dist/agent-generator/templates/core/workflow-review.js +104 -0
  185. package/dist/agent-generator/templates/core/workflow-review.js.map +1 -0
  186. package/dist/agent-generator/templates/domain/index.d.ts +22 -0
  187. package/dist/agent-generator/templates/domain/index.d.ts.map +1 -0
  188. package/dist/agent-generator/templates/domain/index.js +1176 -0
  189. package/dist/agent-generator/templates/domain/index.js.map +1 -0
  190. package/dist/agent-generator/templates/stack/index.d.ts +8 -0
  191. package/dist/agent-generator/templates/stack/index.d.ts.map +1 -0
  192. package/dist/agent-generator/templates/stack/index.js +695 -0
  193. package/dist/agent-generator/templates/stack/index.js.map +1 -0
  194. package/dist/agent-generator/templates/template-helpers.d.ts +75 -0
  195. package/dist/agent-generator/templates/template-helpers.d.ts.map +1 -0
  196. package/dist/agent-generator/templates/template-helpers.js +726 -0
  197. package/dist/agent-generator/templates/template-helpers.js.map +1 -0
  198. package/dist/agent-generator/types.d.ts +196 -0
  199. package/dist/agent-generator/types.d.ts.map +1 -0
  200. package/dist/agent-generator/types.js +27 -0
  201. package/dist/agent-generator/types.js.map +1 -0
  202. package/dist/analyzer.d.ts +5 -0
  203. package/dist/analyzer.d.ts.map +1 -1
  204. package/dist/analyzer.js +35 -4
  205. package/dist/analyzer.js.map +1 -1
  206. package/dist/analyzers/forecast.d.ts +85 -0
  207. package/dist/analyzers/forecast.d.ts.map +1 -0
  208. package/dist/analyzers/forecast.js +337 -0
  209. package/dist/analyzers/forecast.js.map +1 -0
  210. package/dist/analyzers/git-cache.d.ts +7 -0
  211. package/dist/analyzers/git-cache.d.ts.map +1 -0
  212. package/dist/analyzers/git-cache.js +41 -0
  213. package/dist/analyzers/git-cache.js.map +1 -0
  214. package/dist/analyzers/git-history.d.ts +113 -0
  215. package/dist/analyzers/git-history.d.ts.map +1 -0
  216. package/dist/analyzers/git-history.js +333 -0
  217. package/dist/analyzers/git-history.js.map +1 -0
  218. package/dist/analyzers/index.d.ts +10 -0
  219. package/dist/analyzers/index.d.ts.map +1 -0
  220. package/dist/analyzers/index.js +7 -0
  221. package/dist/analyzers/index.js.map +1 -0
  222. package/dist/analyzers/temporal-scorer.d.ts +72 -0
  223. package/dist/analyzers/temporal-scorer.d.ts.map +1 -0
  224. package/dist/analyzers/temporal-scorer.js +140 -0
  225. package/dist/analyzers/temporal-scorer.js.map +1 -0
  226. package/dist/cli.d.ts +2 -3
  227. package/dist/cli.d.ts.map +1 -1
  228. package/dist/cli.js +275 -113
  229. package/dist/cli.js.map +1 -1
  230. package/dist/html-reporter.d.ts +3 -1
  231. package/dist/html-reporter.d.ts.map +1 -1
  232. package/dist/html-reporter.js +248 -12
  233. package/dist/html-reporter.js.map +1 -1
  234. package/dist/index.d.ts +16 -3
  235. package/dist/index.d.ts.map +1 -1
  236. package/dist/index.js +63 -4
  237. package/dist/index.js.map +1 -1
  238. package/dist/project-summarizer.d.ts +18 -0
  239. package/dist/project-summarizer.d.ts.map +1 -0
  240. package/dist/project-summarizer.js +306 -0
  241. package/dist/project-summarizer.js.map +1 -0
  242. package/dist/refactor-reporter.js +1 -1
  243. package/dist/types.d.ts +13 -0
  244. package/dist/types.d.ts.map +1 -1
  245. package/package.json +12 -3
  246. package/src/agent-generator/context-enricher.ts +643 -0
  247. package/src/agent-generator/domain-inferrer.ts +625 -0
  248. package/src/agent-generator/framework-detector.ts +669 -0
  249. package/src/agent-generator/index.ts +555 -0
  250. package/src/agent-generator/stack-detector.ts +103 -0
  251. package/src/agent-generator/templates/core/agents.ts +1293 -0
  252. package/src/agent-generator/templates/core/architecture-rules.ts +287 -0
  253. package/src/agent-generator/templates/core/general-rules.ts +306 -0
  254. package/src/agent-generator/templates/core/index-md.ts +260 -0
  255. package/src/agent-generator/templates/core/orchestrator.ts +459 -0
  256. package/src/agent-generator/templates/core/preflight.ts +215 -0
  257. package/src/agent-generator/templates/core/quality-gates.ts +256 -0
  258. package/src/agent-generator/templates/core/security-rules.ts +543 -0
  259. package/src/agent-generator/templates/core/skills-generator.ts +236 -0
  260. package/src/agent-generator/templates/core/workflow-fix-bug.ts +239 -0
  261. package/src/agent-generator/templates/core/workflow-new-feature.ts +323 -0
  262. package/src/agent-generator/templates/core/workflow-review.ts +106 -0
  263. package/src/agent-generator/templates/domain/index.ts +1201 -0
  264. package/src/agent-generator/templates/stack/index.ts +705 -0
  265. package/src/agent-generator/templates/template-helpers.ts +776 -0
  266. package/src/agent-generator/types.ts +232 -0
  267. package/src/analyzer.ts +38 -4
  268. package/src/analyzers/forecast.ts +496 -0
  269. package/src/analyzers/git-cache.ts +52 -0
  270. package/src/analyzers/git-history.ts +488 -0
  271. package/src/analyzers/index.ts +33 -0
  272. package/src/analyzers/temporal-scorer.ts +227 -0
  273. package/src/cli.ts +316 -117
  274. package/src/html-reporter.ts +263 -13
  275. package/src/index.ts +92 -9
  276. package/src/project-summarizer.ts +347 -0
  277. package/src/refactor-reporter.ts +1 -1
  278. package/src/types.ts +10 -0
  279. package/tests/agent-generator.test.ts +411 -0
  280. package/tests/analyzers-integration.test.ts +174 -0
  281. package/tests/architect-adapter-enrichment.test.ts +9 -0
  282. package/tests/context-enricher.test.ts +971 -0
  283. package/tests/forecast.test.ts +509 -0
  284. package/tests/framework-detector.test.ts +1172 -0
  285. package/tests/git-history.test.ts +254 -0
  286. package/tests/scanner.test.ts +7 -8
  287. package/tests/scorer.test.ts +588 -0
  288. package/tests/stack-detector.test.ts +241 -0
  289. package/tests/template-generation.test.ts +706 -0
  290. package/tests/template-helpers.test.ts +1152 -0
  291. package/tests/temporal-scorer.test.ts +307 -0
  292. package/dist/agent-generator.d.ts +0 -106
  293. package/dist/agent-generator.d.ts.map +0 -1
  294. package/dist/agent-generator.js +0 -1398
  295. package/dist/agent-generator.js.map +0 -1
  296. package/src/agent-generator.ts +0 -1526
@@ -0,0 +1,1176 @@
1
+ /**
2
+ * Domain templates — C4, BDD, TDD, ADR, Threat Model.
3
+ * Reutilizable templates referenced by workflows and agents.
4
+ */
5
+ /**
6
+ * Helper to safely extract enriched context
7
+ */
8
+ function getEnriched(ctx) {
9
+ if (ctx && 'domain' in ctx) {
10
+ return ctx;
11
+ }
12
+ return {};
13
+ }
14
+ /**
15
+ * Generate C4 Architecture template with optional pre-filled examples
16
+ */
17
+ export function generateC4Template(ctx) {
18
+ const enriched = getEnriched(ctx);
19
+ const domain = enriched.domain;
20
+ const modules = enriched.modules || [];
21
+ const endpoints = enriched.endpoints || [];
22
+ const integrations = domain?.integrations || [];
23
+ // Build Level 1 content
24
+ let level1Content = `Atores:
25
+ - [ator 1]: [descrição do papel]
26
+ - [ator 2]: [descrição do papel]`;
27
+ if (domain?.businessEntities && domain.businessEntities.length > 0) {
28
+ const actorsFromEntities = domain.businessEntities.slice(0, 2).map((e) => `- ${e.name}: Entidade de negócio`).join('\n');
29
+ level1Content = `Atores:\n${actorsFromEntities}`;
30
+ }
31
+ let externalSystems = `- [sistema 1]: [como interage]
32
+ - [sistema 2]: [como interage]`;
33
+ if (integrations.length > 0) {
34
+ externalSystems = integrations
35
+ .map((i) => `- ${i.name} (${i.type}): Integração de negócio`)
36
+ .join('\n');
37
+ }
38
+ // Build Level 2 content
39
+ let containerDiagram = `┌──────────────┐ ┌──────────────┐ ┌──────────────┐
40
+ │ Frontend │───▶│ Backend │───▶│ Database │
41
+ │ (Web/App) │ │ (API) │ │ (PostgreSQL)│
42
+ └──────────────┘ └──────────────┘ └──────────────┘
43
+
44
+
45
+ ┌──────────────┐
46
+ │ External │
47
+ │ Service │
48
+ └──────────────┘`;
49
+ if (ctx && 'stack' in ctx && ctx.stack) {
50
+ const stack = ctx.stack;
51
+ let frontendLabel = stack.hasFrontend ? `${stack.frameworks[0] || 'Frontend'}` : '[Frontend]';
52
+ let backendLabel = stack.frameworks[1] || 'Backend';
53
+ let dbLabel = '[Database]';
54
+ if (stack.hasDatabase) {
55
+ dbLabel = stack.frameworks.includes('PostgreSQL') ? 'PostgreSQL' : 'Database';
56
+ }
57
+ containerDiagram = `┌──────────────┐ ┌──────────────┐ ┌──────────────┐
58
+ │ ${frontendLabel.padEnd(11)}│───▶│ ${backendLabel.padEnd(11)}│───▶│ ${dbLabel.padEnd(11)}│
59
+ └──────────────┘ └──────────────┘ └──────────────┘`;
60
+ }
61
+ // Build Level 3 content
62
+ let componentContent = `Módulo: [nome]
63
+ ├── Controller: [nome] — [responsabilidade]
64
+ ├── Service: [nome] — [responsabilidade]
65
+ ├── Entity: [nome] — [campos principais]
66
+ ├── DTO: [nome] — [campos de request/response]
67
+ └── Tests: [lista de testes]`;
68
+ if (modules.length > 0) {
69
+ const firstModule = modules[0];
70
+ const controllers = firstModule.controllers.slice(0, 2).join(', ') || '[Controllers]';
71
+ const services = firstModule.services.slice(0, 2).join(', ') || '[Services]';
72
+ const entities = firstModule.entities.slice(0, 1).join(', ') || '[Entities]';
73
+ componentContent = `Módulo: ${firstModule.name}
74
+ ├── Controller: ${controllers} — Expõe endpoints REST
75
+ ├── Service: ${services} — Lógica de negócio
76
+ ├── Entity: ${entities} — Persistência de dados
77
+ ├── DTO: [Request/Response]
78
+ └── Tests: ${firstModule.testFiles.length > 0 ? 'Implementados' : 'Pendentes'}`;
79
+ }
80
+ // Build Level 4 content — framework-aware code example
81
+ const stack = ctx && 'stack' in ctx ? ctx.stack : undefined;
82
+ const langs = stack ? stack.languages.map((l) => l.toLowerCase()) : [];
83
+ const isPython = langs.includes('python');
84
+ const isDart = langs.includes('dart');
85
+ const isJava = langs.includes('java') || langs.includes('kotlin');
86
+ const isGo = langs.includes('go');
87
+ const isRust = langs.includes('rust');
88
+ let level4Lang = 'typescript';
89
+ let level4Content = `interface IExemploService {
90
+ metodo(param: Tipo): Promise<Retorno>;
91
+ }`;
92
+ if (isPython) {
93
+ level4Lang = 'python';
94
+ level4Content = `class IExemploService(ABC):
95
+ @abstractmethod
96
+ async def metodo(self, param: Tipo) -> Retorno:
97
+ ...`;
98
+ }
99
+ else if (isDart) {
100
+ level4Lang = 'dart';
101
+ level4Content = `abstract class IExemploService {
102
+ Future<Retorno> metodo(Tipo param);
103
+ }`;
104
+ }
105
+ else if (isJava) {
106
+ level4Lang = 'java';
107
+ level4Content = `public interface IExemploService {
108
+ Retorno metodo(Tipo param);
109
+ }`;
110
+ }
111
+ else if (isGo) {
112
+ level4Lang = 'go';
113
+ level4Content = `type ExemploService interface {
114
+ Metodo(param Tipo) (Retorno, error)
115
+ }`;
116
+ }
117
+ else if (isRust) {
118
+ level4Lang = 'rust';
119
+ level4Content = `trait ExemploService {
120
+ fn metodo(&self, param: Tipo) -> Result<Retorno, Error>;
121
+ }`;
122
+ }
123
+ if (endpoints.length > 0) {
124
+ const firstEndpoint = endpoints[0];
125
+ if (isPython) {
126
+ level4Content = `class I${firstEndpoint.handler}Service(ABC):
127
+ # ${firstEndpoint.method} ${firstEndpoint.path}
128
+ @abstractmethod
129
+ async def handle_${firstEndpoint.handler.toLowerCase()}(self, req: Request) -> Response:
130
+ ...`;
131
+ }
132
+ else if (isDart) {
133
+ level4Content = `abstract class I${firstEndpoint.handler}Service {
134
+ // ${firstEndpoint.method} ${firstEndpoint.path}
135
+ Future<Response> handle${firstEndpoint.handler}(Request req);
136
+ }`;
137
+ }
138
+ else if (isJava) {
139
+ level4Content = `public interface I${firstEndpoint.handler}Service {
140
+ // ${firstEndpoint.method} ${firstEndpoint.path}
141
+ Response handle${firstEndpoint.handler}(Request req);
142
+ }`;
143
+ }
144
+ else if (isGo) {
145
+ level4Content = `type ${firstEndpoint.handler}Service interface {
146
+ // ${firstEndpoint.method} ${firstEndpoint.path}
147
+ Handle${firstEndpoint.handler}(req *Request) (*Response, error)
148
+ }`;
149
+ }
150
+ else {
151
+ level4Content = `interface I${firstEndpoint.handler}Service {
152
+ // ${firstEndpoint.method} ${firstEndpoint.path}
153
+ handle${firstEndpoint.handler}(req: Request): Promise<Response>;
154
+ }`;
155
+ }
156
+ }
157
+ return `# 🏗️ Template: Arquitetura C4
158
+
159
+ > Preencher os 4 níveis relevantes para a feature/mudança.
160
+
161
+ ---
162
+
163
+ ## Nível 1 — Contexto
164
+
165
+ > Visão de pássaro: quem são os atores e sistemas envolvidos?
166
+
167
+ \`\`\`
168
+ ${level1Content}
169
+
170
+ Sistemas Externos:
171
+ ${externalSystems}
172
+
173
+ Fluxo de dados:
174
+ [ator] → [sistema] → [nosso sistema] → [resposta]
175
+ \`\`\`
176
+
177
+ ---
178
+
179
+ ## Nível 2 — Container
180
+
181
+ > Quais serviços, apps, bancos de dados são tocados?
182
+
183
+ \`\`\`
184
+ ${containerDiagram}
185
+ \`\`\`
186
+
187
+ ---
188
+
189
+ ## Nível 3 — Componente
190
+
191
+ > Quais módulos, classes, serviços são criados ou modificados?
192
+
193
+ \`\`\`
194
+ ${componentContent}
195
+ \`\`\`
196
+
197
+ ---
198
+
199
+ ## Nível 4 — Código (se complexo)
200
+
201
+ > Interfaces, tipos, contratos. Apenas para decisões complexas.
202
+
203
+ \`\`\`${level4Lang}
204
+ ${level4Content}
205
+ \`\`\`
206
+
207
+ ---
208
+
209
+ ## Decisões Arquiteturais
210
+
211
+ Se a decisão é significativa → criar ADR separado (ver template ADR).
212
+ `;
213
+ }
214
+ /**
215
+ * Generate BDD template with optional pre-filled examples from project domain
216
+ */
217
+ export function generateBddTemplate(ctx) {
218
+ const enriched = getEnriched(ctx);
219
+ const domain = enriched.domain;
220
+ const businessEntities = domain?.businessEntities || [];
221
+ const compliance = domain?.compliance || [];
222
+ let featureName = '[Nome da Feature]';
223
+ let exampleScenario = ` Scenario: [cenário principal - sucesso]
224
+ Given [contexto / pré-condição]
225
+ And [contexto adicional, se necessário]
226
+ When [ação do usuário]
227
+ Then [resultado esperado]
228
+ And [efeito colateral, se houver]`;
229
+ // Generate example scenario from first business entity
230
+ if (businessEntities.length > 0) {
231
+ const entity = businessEntities[0];
232
+ featureName = `Criar e Validar ${entity.name}`;
233
+ exampleScenario = ` Scenario: Criar ${entity.name} com sucesso
234
+ Given o usuário está no formulário de criação de ${entity.name}
235
+ And todos os campos obrigatórios estão vazios
236
+ When o usuário preenche os campos corretamente
237
+ Then a entidade é persistida no banco de dados
238
+ And uma mensagem de sucesso é exibida ao usuário`;
239
+ }
240
+ let complianceScenario = ` Scenario: [cenário de acesso negado]
241
+ Given [usuário sem permissão]
242
+ When [tenta acessar recurso]
243
+ Then [resposta 403 / redirect]`;
244
+ // Add compliance-specific scenario if applicable
245
+ if (compliance.length > 0) {
246
+ const comp = compliance[0];
247
+ if (comp.name === 'LGPD') {
248
+ complianceScenario = ` Scenario: Usuário solicita exclusão de dados sob LGPD
249
+ Given um usuário autenticado no sistema
250
+ When o usuário solicita a exclusão de seus dados pessoais
251
+ Then todos os seus registros são anonimizados ou removidos
252
+ And a solicitação é registrada em audit log`;
253
+ }
254
+ else if (comp.name === 'HIPAA') {
255
+ complianceScenario = ` Scenario: Acesso a dados sensíveis de paciente
256
+ Given um profissional de saúde autenticado
257
+ When o profissional acessa registros de paciente
258
+ Then o acesso é registrado com timestamp e usuário
259
+ And a ação é auditada para compliance`;
260
+ }
261
+ }
262
+ let domainSpecificSection = '';
263
+ if (domain?.domain === 'fintech' || domain?.domain === 'payment') {
264
+ domainSpecificSection = `
265
+
266
+ # ── Cenários de Fintech ──
267
+
268
+ Scenario: Transação com saldo insuficiente
269
+ Given a conta do usuário tem saldo de R$ 50
270
+ When o usuário tenta transferir R$ 100
271
+ Then a transação é rejeitada
272
+ And a mensagem "Saldo insuficiente" é exibida
273
+
274
+ Scenario: Taxa de câmbio atualizada
275
+ Given uma transação internacional está pendente
276
+ When a taxa de câmbio muda de 5.0 para 5.2
277
+ Then o valor em reais é recalculado
278
+ And o usuário é notificado da mudança`;
279
+ }
280
+ else if (domain?.domain === 'tax' || domain?.subDomain === 'tax-processing') {
281
+ domainSpecificSection = `
282
+
283
+ # ── Cenários de Impostos ──
284
+
285
+ Scenario: Calcular imposto sobre renda
286
+ Given um contribuinte com rendimento mensal de R$ 5000
287
+ When o sistema calcula o imposto devido
288
+ Then o valor segue a tabela progressiva do IRPF
289
+ And o resultado é salvo no banco de dados
290
+
291
+ Scenario: Gerar DARF automático
292
+ Given uma obrigação de imposto vencendo amanhã
293
+ When o sistema processa as obrigações pendentes
294
+ Then um DARF é gerado automaticamente
295
+ And uma notificação é enviada ao contribuinte`;
296
+ }
297
+ return `# 🧪 Template: BDD — Behavior-Driven Development
298
+
299
+ > Um cenário para cada critério de aceite + cenários de erro + edge cases.
300
+
301
+ ---
302
+
303
+ ## Feature: ${featureName}
304
+
305
+ \`\`\`gherkin
306
+ Feature: ${featureName}
307
+ Como usuário,
308
+ Quero interagir com ${businessEntities[0]?.name || 'o sistema'},
309
+ Para alcançar meu objetivo de negócio.
310
+
311
+ # ── Happy Path ──
312
+
313
+ ${exampleScenario}
314
+
315
+ # ── Validações ──
316
+
317
+ Scenario: Validação de dados obrigatórios
318
+ Given um formulário de criação
319
+ When o usuário tenta enviar sem preencher campos obrigatórios
320
+ Then mensagens de erro são exibidas para cada campo
321
+
322
+ # ── Edge Cases ──
323
+
324
+ Scenario: Lidar com valores boundary
325
+ Given o sistema aceita valores de 0 a 999999.99
326
+ When o usuário tenta inserir um valor fora do range
327
+ Then um erro de validação é retornado
328
+
329
+ # ── Permissões ──
330
+
331
+ ${complianceScenario}${domainSpecificSection}
332
+ \`\`\`
333
+
334
+ ---
335
+
336
+ ## Checklist
337
+
338
+ \`\`\`
339
+ □ Cada critério de aceite tem ≥ 1 cenário
340
+ □ Happy path coberto
341
+ □ Error paths cobertos
342
+ □ Edge cases cobertos
343
+ □ Permissões/autenticação cobertos
344
+ □ Cenários são independentes entre si
345
+ \`\`\`
346
+ `;
347
+ }
348
+ /**
349
+ * Generate TDD template with optional pre-filled examples
350
+ */
351
+ export function generateTddTemplate(ctx) {
352
+ const enriched = getEnriched(ctx);
353
+ const modules = enriched.modules || [];
354
+ const endpoints = enriched.endpoints || [];
355
+ const stack = ctx && 'stack' in ctx ? ctx.stack : undefined;
356
+ let testFramework = 'jest';
357
+ let exampleTest = ` it('should [resultado esperado] when [condição]', () => {
358
+ // Arrange
359
+ const input = ...;
360
+
361
+ // Act
362
+ const result = metodo(input);
363
+
364
+ // Assert
365
+ expect(result).toEqual(expected);
366
+ });`;
367
+ // Detect test framework from stack (case-insensitive comparison)
368
+ if (stack) {
369
+ const langs = stack.languages.map((l) => l.toLowerCase());
370
+ if (langs.includes('python')) {
371
+ testFramework = 'pytest';
372
+ }
373
+ else if (langs.includes('dart')) {
374
+ testFramework = 'flutter_test';
375
+ }
376
+ else if (langs.includes('java') || langs.includes('kotlin')) {
377
+ testFramework = 'junit';
378
+ }
379
+ else if (langs.includes('go')) {
380
+ testFramework = 'go_test';
381
+ }
382
+ else if (langs.includes('rust')) {
383
+ testFramework = 'cargo_test';
384
+ }
385
+ }
386
+ let moduleName = '[Nome do Módulo/Classe]';
387
+ let methodName = '[método/função]';
388
+ let exampleModule = modules[0];
389
+ if (exampleModule) {
390
+ moduleName = exampleModule.name;
391
+ const service = exampleModule.services[0] || 'Service';
392
+ methodName = `create${service.replace('Service', '')}`;
393
+ if (testFramework === 'pytest') {
394
+ exampleTest = ` def test_should_create_entity_successfully(self):
395
+ # Arrange
396
+ input_data = {"name": "Test Entity"}
397
+
398
+ # Act
399
+ result = service.${methodName}(input_data)
400
+
401
+ # Assert
402
+ assert result is not None
403
+ assert result.name == "Test Entity"`;
404
+ }
405
+ else if (testFramework === 'flutter_test') {
406
+ exampleTest = ` test('should create entity successfully', () async {
407
+ // Arrange
408
+ final input = CreateRequest(name: 'Test');
409
+
410
+ // Act
411
+ final result = await service.${methodName}(input);
412
+
413
+ // Assert
414
+ expect(result, isNotNull);
415
+ expect(result.name, equals('Test'));
416
+ });`;
417
+ }
418
+ else if (testFramework === 'go_test') {
419
+ exampleTest = `func TestShould_Create${moduleName}_Successfully(t *testing.T) {
420
+ // Arrange
421
+ input := ${moduleName}Input{Name: "Test Entity"}
422
+
423
+ // Act
424
+ result, err := service.${methodName}(input)
425
+
426
+ // Assert
427
+ assert.NoError(t, err)
428
+ assert.NotNil(t, result)
429
+ assert.Equal(t, "Test Entity", result.Name)
430
+ }`;
431
+ }
432
+ else if (testFramework === 'cargo_test') {
433
+ exampleTest = `#[test]
434
+ fn test_should_create_${moduleName.toLowerCase()}_successfully() {
435
+ // Arrange
436
+ let input = ${moduleName}Input { name: "Test Entity".to_string() };
437
+
438
+ // Act
439
+ let result = service.${methodName}(&input);
440
+
441
+ // Assert
442
+ assert!(result.is_ok());
443
+ assert_eq!(result.unwrap().name, "Test Entity");
444
+ }`;
445
+ }
446
+ else if (testFramework === 'junit') {
447
+ exampleTest = ` @Test
448
+ void shouldCreate${moduleName}Successfully() {
449
+ // Arrange
450
+ var input = new ${moduleName}Input("Test Entity");
451
+
452
+ // Act
453
+ var result = service.${methodName}(input);
454
+
455
+ // Assert
456
+ assertNotNull(result);
457
+ assertEquals("Test Entity", result.getName());
458
+ }`;
459
+ }
460
+ else {
461
+ exampleTest = ` it('should create ${moduleName} successfully', () => {
462
+ // Arrange
463
+ const input = { name: 'Test Entity' };
464
+
465
+ // Act
466
+ const result = service.${methodName}(input);
467
+
468
+ // Assert
469
+ expect(result).toBeDefined();
470
+ expect(result.name).toBe('Test Entity');
471
+ });`;
472
+ }
473
+ }
474
+ let endpointTest = '';
475
+ if (endpoints.length > 0) {
476
+ const endpoint = endpoints[0];
477
+ if (testFramework === 'pytest') {
478
+ endpointTest = `
479
+
480
+ def test_${endpoint.method.toLowerCase()}_${endpoint.path.replace(/\//g, '_')}():
481
+ """Test ${endpoint.method} ${endpoint.path}"""
482
+ # Arrange
483
+ client = TestClient(app)
484
+
485
+ # Act
486
+ response = client.${endpoint.method.toLowerCase()}("${endpoint.path}")
487
+
488
+ # Assert
489
+ assert response.status_code == 200`;
490
+ }
491
+ else if (testFramework === 'flutter_test') {
492
+ endpointTest = `
493
+
494
+ testWidgets('should ${endpoint.method.toLowerCase()} ${endpoint.path} correctly', (WidgetTester tester) async {
495
+ // Arrange
496
+ when(mockClient.${endpoint.method.toLowerCase()}(endpoint)).thenAnswer((_) async => Response('{}', 200));
497
+
498
+ // Act
499
+ final result = await client.${endpoint.method.toLowerCase()}(endpoint);
500
+
501
+ // Assert
502
+ expect(result.statusCode, equals(200));
503
+ });`;
504
+ }
505
+ else if (testFramework === 'go_test') {
506
+ endpointTest = `
507
+
508
+ func Test_${endpoint.method}_${endpoint.path.replace(/\//g, '_')}(t *testing.T) {
509
+ // Arrange
510
+ req := httptest.NewRequest("${endpoint.method}", "${endpoint.path}", nil)
511
+ w := httptest.NewRecorder()
512
+
513
+ // Act
514
+ handler.ServeHTTP(w, req)
515
+
516
+ // Assert
517
+ assert.Equal(t, http.StatusOK, w.Code)
518
+ }`;
519
+ }
520
+ else if (testFramework === 'cargo_test') {
521
+ endpointTest = `
522
+
523
+ #[actix_web::test]
524
+ async fn test_${endpoint.method.toLowerCase()}_${endpoint.path.replace(/\//g, '_')}() {
525
+ // Arrange
526
+ let app = test::init_service(App::new().configure(routes)).await;
527
+ let req = test::TestRequest::${endpoint.method.toLowerCase()}().uri("${endpoint.path}").to_request();
528
+
529
+ // Act
530
+ let resp = test::call_service(&app, req).await;
531
+
532
+ // Assert
533
+ assert!(resp.status().is_success());
534
+ }`;
535
+ }
536
+ else if (testFramework === 'junit') {
537
+ endpointTest = `
538
+
539
+ @Test
540
+ void should${endpoint.method}${endpoint.handler}Correctly() throws Exception {
541
+ // Act & Assert
542
+ mockMvc.perform(${endpoint.method.toLowerCase()}("${endpoint.path}"))
543
+ .andExpect(status().isOk());
544
+ }`;
545
+ }
546
+ else {
547
+ endpointTest = `
548
+
549
+ it('should ${endpoint.method.toLowerCase()} ${endpoint.path} correctly', async () => {
550
+ // Arrange
551
+ const endpoint = '${endpoint.path}';
552
+
553
+ // Act
554
+ const response = await request(app).${endpoint.method.toLowerCase()}(endpoint);
555
+
556
+ // Assert
557
+ expect(response.status).toBe(200);
558
+ });`;
559
+ }
560
+ }
561
+ const structureLabel = testFramework === 'pytest' ? 'def test_' : testFramework === 'flutter_test' ? 'test(' : 'describe(';
562
+ const openingBracket = testFramework === 'pytest' ? ':' : testFramework === 'flutter_test' ? ', () async {' : ", () => {";
563
+ return `# 🔬 Template: TDD — Test-Driven Development
564
+
565
+ > RED → GREEN → REFACTOR. Nesta ordem. Sempre.
566
+
567
+ ---
568
+
569
+ ## Estrutura de Testes (${testFramework})
570
+
571
+ \`\`\`${testFramework === 'pytest' ? 'python' : testFramework === 'flutter_test' ? 'dart' : testFramework === 'go_test' ? 'go' : testFramework === 'cargo_test' ? 'rust' : testFramework === 'junit' ? 'java' : 'typescript'}
572
+ ${testFramework === 'pytest'
573
+ ? `import pytest
574
+ from app.services.${moduleName.toLowerCase()} import ${moduleName}Service
575
+
576
+ class Test${moduleName}:
577
+ """Testes para ${moduleName}"""
578
+
579
+ ${exampleTest}
580
+
581
+ def test_should_throw_error_when_invalid_input(self):
582
+ # Arrange
583
+ invalid_input = None
584
+
585
+ # Act & Assert
586
+ with pytest.raises(ValueError):
587
+ service.${methodName}(invalid_input)`
588
+ : testFramework === 'flutter_test'
589
+ ? `import 'package:flutter_test/flutter_test.dart';
590
+ import 'package:${moduleName.toLowerCase()}/services/${moduleName.toLowerCase()}_service.dart';
591
+
592
+ void main() {
593
+ group('${moduleName}Service', () {
594
+
595
+ ${exampleTest}
596
+
597
+ test('should throw exception when input is invalid', () {
598
+ // Arrange
599
+ final invalid = null;
600
+
601
+ // Act & Assert
602
+ expect(() => service.${methodName}(invalid), throwsException);
603
+ });${endpointTest}
604
+ });
605
+ }`
606
+ : testFramework === 'go_test'
607
+ ? `package ${moduleName.toLowerCase()}_test
608
+
609
+ import (
610
+ "testing"
611
+ "net/http"
612
+ "net/http/httptest"
613
+ "github.com/stretchr/testify/assert"
614
+ )
615
+
616
+ // ── Happy Path ──
617
+ ${exampleTest}
618
+
619
+ // ── Error Path ──
620
+ func TestShould_Return_Error_When_InvalidInput(t *testing.T) {
621
+ // Arrange
622
+ input := ${moduleName}Input{}
623
+
624
+ // Act
625
+ _, err := service.${methodName}(input)
626
+
627
+ // Assert
628
+ assert.Error(t, err)
629
+ }${endpointTest}`
630
+ : testFramework === 'cargo_test'
631
+ ? `#[cfg(test)]
632
+ mod tests {
633
+ use super::*;
634
+
635
+ // ── Happy Path ──
636
+ ${exampleTest}
637
+
638
+ // ── Error Path ──
639
+ #[test]
640
+ fn test_should_return_error_when_invalid_input() {
641
+ // Arrange
642
+ let input = ${moduleName}Input { name: "".to_string() };
643
+
644
+ // Act
645
+ let result = service.${methodName}(&input);
646
+
647
+ // Assert
648
+ assert!(result.is_err());
649
+ }${endpointTest}
650
+ }`
651
+ : testFramework === 'junit'
652
+ ? `import org.junit.jupiter.api.Test;
653
+ import static org.junit.jupiter.api.Assertions.*;
654
+
655
+ class ${moduleName}Test {
656
+
657
+ // ── Happy Path ──
658
+ ${exampleTest}
659
+
660
+ // ── Error Path ──
661
+ @Test
662
+ void shouldThrowWhenInvalidInput() {
663
+ // Arrange
664
+ var invalidInput = new ${moduleName}Input(null);
665
+
666
+ // Act & Assert
667
+ assertThrows(IllegalArgumentException.class,
668
+ () -> service.${methodName}(invalidInput));
669
+ }${endpointTest}
670
+ }`
671
+ : `describe('${moduleName}', () => {
672
+
673
+ describe('${methodName}', () => {
674
+
675
+ // ── Happy Path ──
676
+ ${exampleTest}
677
+
678
+ // ── Error Path ──
679
+ it('should throw [erro] when [condição inválida]', () => {
680
+ // Arrange
681
+ const invalidInput = undefined;
682
+
683
+ // Act & Assert
684
+ expect(() => service.${methodName}(invalidInput)).toThrow(Error);
685
+ });
686
+
687
+ // ── Boundary ──
688
+ it('should handle empty input', () => {
689
+ // Arrange
690
+ const boundaryInput = {};
691
+
692
+ // Act
693
+ const result = service.${methodName}(boundaryInput);
694
+
695
+ // Assert
696
+ expect(result).toBeDefined();
697
+ });${endpointTest}
698
+ });
699
+ });`}
700
+ \`\`\`
701
+
702
+ ---
703
+
704
+ ## Ciclo TDD
705
+
706
+ \`\`\`
707
+ 1. RED: Escrever teste que FALHA
708
+ 2. GREEN: Escrever código MÍNIMO para passar
709
+ 3. REFACTOR: Melhorar sem quebrar testes
710
+ 4. REPEAT
711
+ \`\`\`
712
+
713
+ ---
714
+
715
+ ## Checklist
716
+
717
+ \`\`\`
718
+ □ Teste escrito ANTES do código
719
+ □ Teste falha antes da implementação (RED)
720
+ □ Implementação mínima para passar (GREEN)
721
+ □ Refatoração sem quebrar testes (REFACTOR)
722
+ □ Happy path coberto
723
+ □ Error path coberto
724
+ □ Boundary cases cobertos
725
+ □ Cobertura atinge o mínimo do projeto
726
+ \`\`\`
727
+ `;
728
+ }
729
+ /**
730
+ * Generate ADR template with optional pre-filled examples from tech stack
731
+ */
732
+ export function generateAdrTemplate(ctx) {
733
+ const enriched = getEnriched(ctx);
734
+ const stack = ctx && 'stack' in ctx ? ctx.stack : undefined;
735
+ const domain = enriched.domain;
736
+ let exampleDecision = '[Título da Decisão]';
737
+ let contextDescription = '[descrever o contexto de negócio e técnico]';
738
+ let decisionDescription = '[descrever a decisão claramente]';
739
+ let alternativeOne = '[alternativa 1]';
740
+ let alternativeTwo = '[alternativa 2]';
741
+ // Generate tech stack specific examples (framework-aware)
742
+ if (stack) {
743
+ const framework = stack.frameworks[0] || 'Backend Framework';
744
+ const database = stack.frameworks.find((f) => ['PostgreSQL', 'MongoDB', 'MySQL', 'SQLite', 'Redis'].includes(f)) || 'PostgreSQL';
745
+ const adrLangs = stack.languages.map((l) => l.toLowerCase());
746
+ const adrIsPython = adrLangs.includes('python');
747
+ const adrIsDart = adrLangs.includes('dart');
748
+ const adrIsGo = adrLangs.includes('go');
749
+ const adrIsJava = adrLangs.includes('java') || adrLangs.includes('kotlin');
750
+ exampleDecision = `Uso de ${framework} para Backend`;
751
+ if (adrIsPython) {
752
+ contextDescription = `O projeto requer uma API REST escalável com Python. Precisamos escolher um framework que:
753
+ - Suporte async/await nativo
754
+ - Tenha tipagem com Pydantic e validação automática
755
+ - Tenha comunidade ativa e documentação excelente`;
756
+ decisionDescription = `Decidimos usar ${framework} como framework backend principal. ${framework} oferece:
757
+ - Async/await nativo com alto desempenho
758
+ - Validação automática via Pydantic
759
+ - Documentação OpenAPI/Swagger automática
760
+ - Suporte a bancos de dados (SQLAlchemy, Tortoise ORM, etc.)`;
761
+ alternativeOne = 'Django REST Framework';
762
+ alternativeTwo = 'Flask + extensões';
763
+ }
764
+ else if (adrIsDart) {
765
+ contextDescription = `O projeto requer um aplicativo mobile multiplataforma. Precisamos escolher um framework que:
766
+ - Suporte iOS e Android com um único codebase
767
+ - Tenha hot-reload e boa experiência de desenvolvimento
768
+ - Tenha widgets nativos e alta performance`;
769
+ decisionDescription = `Decidimos usar ${framework} como framework principal. ${framework} oferece:
770
+ - UI declarativa com widgets nativos
771
+ - Hot-reload para desenvolvimento rápido
772
+ - Compilação nativa para iOS e Android
773
+ - Ecossistema de pacotes via pub.dev`;
774
+ alternativeOne = 'React Native';
775
+ alternativeTwo = 'Kotlin Multiplatform';
776
+ }
777
+ else if (adrIsGo) {
778
+ contextDescription = `O projeto requer um serviço backend de alta performance. Precisamos escolher uma stack que:
779
+ - Tenha concorrência nativa eficiente
780
+ - Suporte compilação estática e deploy simplificado
781
+ - Tenha forte tipagem e performance previsível`;
782
+ decisionDescription = `Decidimos usar ${framework} como framework principal. ${framework} oferece:
783
+ - Goroutines para concorrência eficiente
784
+ - Binário estático único para deploy
785
+ - Performance previsível e baixo footprint
786
+ - Ecossistema robusto de middleware`;
787
+ alternativeOne = 'net/http padrão + chi router';
788
+ alternativeTwo = 'Fiber (Express-like para Go)';
789
+ }
790
+ else if (adrIsJava) {
791
+ contextDescription = `O projeto requer uma API REST enterprise-grade. Precisamos escolher um framework que:
792
+ - Suporte injeção de dependência nativa
793
+ - Tenha ecossistema maduro e produção comprovada
794
+ - Tenha integração com bancos de dados (JPA/Hibernate)`;
795
+ decisionDescription = `Decidimos usar ${framework} como framework backend principal. ${framework} oferece:
796
+ - Injeção de dependência nativa
797
+ - Ecossistema maduro com milhares de extensões
798
+ - Suporte a JPA/Hibernate para persistência
799
+ - Segurança via Spring Security / equivalente`;
800
+ alternativeOne = 'Quarkus (nativo GraalVM)';
801
+ alternativeTwo = 'Micronaut';
802
+ }
803
+ else {
804
+ contextDescription = `O projeto requer uma API REST escalável com TypeScript. Precisamos escolher um framework que:
805
+ - Suporte TypeScript nativo
806
+ - Tenha decorators e dependency injection
807
+ - Tenha comunidade ativa e documentação excelente`;
808
+ decisionDescription = `Decidimos usar ${framework} como framework backend principal. ${framework} oferece:
809
+ - Arquitetura modular built-in
810
+ - Decorators para roteamento e middleware
811
+ - Injeção de dependência nativa
812
+ - Suporte a bancos de dados (TypeORM, Prisma, etc.)`;
813
+ alternativeOne = 'Express.js + middleware customizado';
814
+ alternativeTwo = 'Fastify';
815
+ }
816
+ // Add database-specific ADR if applicable
817
+ let dbDecision = '';
818
+ if (database) {
819
+ dbDecision = `
820
+
821
+ ---
822
+
823
+ ## ADR-002: Banco de Dados ${database}
824
+
825
+ **Status:** accepted
826
+ **Data:** 2024-01-15
827
+ **Autores:** [equipe técnica]
828
+
829
+ ### Contexto
830
+
831
+ Precisamos escolher um banco de dados relacional que:
832
+ - Suporte transações ACID
833
+ - Tenha integração com ${framework}
834
+ - Permita escalabilidade horizontal
835
+
836
+ ### Decisão
837
+
838
+ Escolhemos ${database} como banco de dados principal por:
839
+ - Suporte a JSON nativo
840
+ - Excelente performance em leitura/escrita
841
+ - Integração com ${adrIsPython ? 'SQLAlchemy/Alembic' : adrIsJava ? 'JPA/Hibernate' : adrIsGo ? 'GORM/sqlx' : 'TypeORM/Prisma'} é padrão
842
+
843
+ ### Alternativas Consideradas
844
+
845
+ | # | Alternativa | Prós | Contras |
846
+ |---|-----------|------|---------|
847
+ | 1 | MySQL | Popular, estável | Menos recursos avançados |
848
+ | 2 | MongoDB | Escalável | Sem ACID nativo, schema dinâmico |`;
849
+ return `# 📋 Template: ADR — Architecture Decision Record
850
+
851
+ > Use quando uma decisão técnica é significativa ou controversa.
852
+
853
+ ---
854
+
855
+ ## ADR-001: ${exampleDecision}
856
+
857
+ **Status:** proposed | accepted | deprecated | superseded by ADR-YYY
858
+ **Data:** YYYY-MM-DD
859
+ **Autores:** [quem participou da decisão]
860
+
861
+ ---
862
+
863
+ ### Contexto
864
+
865
+ > Qual é o problema ou necessidade que levou a esta decisão?
866
+
867
+ ${contextDescription}
868
+
869
+ ---
870
+
871
+ ### Decisão
872
+
873
+ > O que foi decidido?
874
+
875
+ ${decisionDescription}
876
+
877
+ ---
878
+
879
+ ### Alternativas Consideradas
880
+
881
+ | # | Alternativa | Prós | Contras | Por que descartada |
882
+ |---|-----------|------|---------|-------------------|
883
+ | 1 | ${alternativeOne} | [prós] | [contras] | [motivo] |
884
+ | 2 | ${alternativeTwo} | [prós] | [contras] | [motivo] |
885
+
886
+ ---
887
+
888
+ ### Consequências
889
+
890
+ **Positivas:**
891
+ - Arquitetura clara e escalável
892
+ - Código mais organizado e testável
893
+ - Comunidade ativa para suporte
894
+
895
+ **Negativas:**
896
+ - Curva de aprendizado para novos desenvolvedores
897
+ - Overhead de dependências
898
+
899
+ **Riscos:**
900
+ - Atualização de versões major — probabilidade: média
901
+
902
+ ---
903
+
904
+ ### Notas
905
+
906
+ - Revisar em 6 meses se a decisão continua válida
907
+ ${dbDecision}`;
908
+ }
909
+ }
910
+ // Add domain-specific ADR section
911
+ let domainAdrs = '';
912
+ if (domain?.domain === 'fintech') {
913
+ domainAdrs = `
914
+
915
+ ---
916
+
917
+ ## ADR-XXX: Criptografia de CPF e Dados Sensíveis
918
+
919
+ **Status:** proposed
920
+ **Data:** YYYY-MM-DD
921
+ **Autores:** [equipe de segurança]
922
+
923
+ ### Contexto
924
+
925
+ Dados de clientes (CPF, CNPJ, dados bancários) são críticos para fintech.
926
+ Precisamos de criptografia de dados sensíveis at-rest.
927
+
928
+ ### Decisão
929
+
930
+ Usar AES-256 para criptografia de dados sensíveis com chaves armazenadas no vault.
931
+
932
+ ### Alternativas Consideradas
933
+
934
+ | # | Alternativa | Segurança | Complexidade |
935
+ |---|-----------|----------|--------------|
936
+ | 1 | AES-256 | Alta | Média |
937
+ | 2 | RSA | Muito Alta | Alta |
938
+ | 3 | Nenhuma | Baixa | Baixa |`;
939
+ }
940
+ else if (domain?.domain === 'healthtech') {
941
+ domainAdrs = `
942
+
943
+ ---
944
+
945
+ ## ADR-XXX: Conformidade HIPAA em Armazenamento
946
+
947
+ **Status:** proposed
948
+ **Data:** YYYY-MM-DD
949
+ **Autores:** [equipe de compliance]
950
+
951
+ ### Contexto
952
+
953
+ Dados de saúde devem estar em conformidade com HIPAA.
954
+ Precisamos garantir criptografia, auditoria e retenção apropriada.
955
+
956
+ ### Decisão
957
+
958
+ Implementar criptografia AES-256, logging de acesso e retenção de dados por 7 anos.`;
959
+ }
960
+ return `# 📋 Template: ADR — Architecture Decision Record
961
+
962
+ > Use quando uma decisão técnica é significativa ou controversa.
963
+
964
+ ---
965
+
966
+ ## ADR-XXX: ${exampleDecision}
967
+
968
+ **Status:** proposed | accepted | deprecated | superseded by ADR-YYY
969
+ **Data:** YYYY-MM-DD
970
+ **Autores:** [quem participou da decisão]
971
+
972
+ ---
973
+
974
+ ### Contexto
975
+
976
+ > Qual é o problema ou necessidade que levou a esta decisão?
977
+
978
+ ${contextDescription}
979
+
980
+ ---
981
+
982
+ ### Decisão
983
+
984
+ > O que foi decidido?
985
+
986
+ ${decisionDescription}
987
+
988
+ ---
989
+
990
+ ### Alternativas Consideradas
991
+
992
+ | # | Alternativa | Prós | Contras | Por que descartada |
993
+ |---|-----------|------|---------|-------------------|
994
+ | 1 | ${alternativeOne} | [prós] | [contras] | [motivo] |
995
+ | 2 | ${alternativeTwo} | [prós] | [contras] | [motivo] |
996
+
997
+ ---
998
+
999
+ ### Consequências
1000
+
1001
+ **Positivas:**
1002
+ - [consequência positiva 1]
1003
+ - [consequência positiva 2]
1004
+
1005
+ **Negativas:**
1006
+ - [consequência negativa 1]
1007
+ - [mitigação: como minimizar]
1008
+
1009
+ **Riscos:**
1010
+ - [risco 1] — probabilidade: [alta/média/baixa]
1011
+
1012
+ ---
1013
+
1014
+ ### Notas
1015
+
1016
+ - [qualquer informação adicional]${domainAdrs}
1017
+ `;
1018
+ }
1019
+ /**
1020
+ * Generate Threat Model template with optional pre-filled domain-specific threats
1021
+ */
1022
+ export function generateThreatModelTemplate(ctx) {
1023
+ const enriched = getEnriched(ctx);
1024
+ const domain = enriched.domain;
1025
+ const businessEntities = domain?.businessEntities || [];
1026
+ const compliance = domain?.compliance || [];
1027
+ let featureName = '[Nome]';
1028
+ let actors = `| [ator 1] | [alto/médio/baixo] | [dados/recursos] |`;
1029
+ let sensitiveData = `| [dado 1] | PII / Financeiro / Auth | [como proteger] |`;
1030
+ let domainSpecificThreats = '';
1031
+ // Generate domain-specific actors and threats
1032
+ if (domain?.domain === 'fintech') {
1033
+ featureName = 'Transferência Bancária';
1034
+ actors = `| Usuário | Alto | Conta bancária, saldo |
1035
+ | Sistema Interno | Alto | Todas as transações |
1036
+ | Banco Parceiro | Médio | Dados de rota |
1037
+ | Auditor (interno) | Médio | Logs de transações |`;
1038
+ sensitiveData = `| CPF | PII | AES-256 at-rest, TLS in-transit |
1039
+ | Número de Conta | Financeiro | AES-256 + masking |
1040
+ | Saldo | Financeiro | Hash verificável |
1041
+ | Histórico de Transações | Auditoria | Criptografado, signed |`;
1042
+ domainSpecificThreats = `
1043
+
1044
+ ---
1045
+
1046
+ ## Ameaças Específicas de Fintech
1047
+
1048
+ | Ameaça | Descrição | Mitigação |
1049
+ |--------|-----------|-----------|
1050
+ | Falsificação de Identidade | Hacker usa CPF falso para abrir conta | Validação com gov API, SMS 2FA |
1051
+ | Tamperização de Saldo | Atacante modifica saldo direto no DB | Checksums, transações com assinatura |
1052
+ | Roubo de Sessão | Hijack de cookie de autenticação | HTTPS, SameSite cookie, token rotation |
1053
+ | Negação de Transferência | Usuário nega ter feito transação | Auditoria, e-mail de confirmação |
1054
+ | Bloqueio de Serviço | DDoS na API de transações | Rate limiting, WAF, CDN |
1055
+ | Escalonamento de Permissão | Admin faz transferência não autorizada | RBAC, audit logging, segregação |`;
1056
+ }
1057
+ else if (domain?.domain === 'tax' || domain?.subDomain === 'tax-processing') {
1058
+ featureName = 'Cálculo e Envio de Imposto';
1059
+ actors = `| Contribuinte | Alto | Declaração, CPF, rendimentos |
1060
+ | Contador | Médio | Dados do cliente, acesso a declaração |
1061
+ | Receita Federal | Médio | Declaração enviada, comprovantes |
1062
+ | Auditor Interno | Médio | Logs de processamento, erros |`;
1063
+ sensitiveData = `| CPF/CNPJ | PII | AES-256, masking em logs |
1064
+ | Rendimentos Totais | Financeiro | Criptografado |
1065
+ | Deduções e Benefícios | Pessoal | Criptografado |
1066
+ | Histórico de Envios | Auditoria | Signed, imutável |`;
1067
+ domainSpecificThreats = `
1068
+
1069
+ ---
1070
+
1071
+ ## Ameaças Específicas de Impostos
1072
+
1073
+ | Ameaça | Descrição | Mitigação |
1074
+ |--------|-----------|-----------|
1075
+ | Falsificação de Receita | Declarar rendimento falso | Cruzamento com dados da Receita Federal |
1076
+ | Tamperização de Cálculo | Hacker reduz imposto devido | Validação automática, recálculo periódico |
1077
+ | Vazamento de Dados | Exposição de CPF/rendimento | Criptografia, LGPD compliance |
1078
+ | Negação de Envio | Usuário nega envio ao fisco | Timestamp assinado, audit log |
1079
+ | Indisponibilidade na Época | Servidor cai no último dia | SLA 99.9%, failover automático |
1080
+ | Acesso não Autorizado | Contador acessa dado de cliente errado | RBAC granular, segregação de dados |`;
1081
+ }
1082
+ else if (domain?.domain === 'healthtech') {
1083
+ featureName = 'Acesso a Histórico Médico';
1084
+ actors = `| Paciente | Alto | Histórico médico, exames, receitas |
1085
+ | Médico | Alto | Prontuário do paciente |
1086
+ | Farmacêutico | Médio | Prescrições, alergias |
1087
+ | Auditor Compliance | Médio | Logs de acesso, consentimento |`;
1088
+ sensitiveData = `| Nome Paciente | PII | Criptografado, HIPAA compliant |
1089
+ | Histórico Médico | Saúde | AES-256, acesso restrito |
1090
+ | Medicamentos | Saúde | Criptografado, masking em logs |
1091
+ | Resultado de Exames | Saúde | Criptografado, assinado digitalmente |`;
1092
+ domainSpecificThreats = `
1093
+
1094
+ ---
1095
+
1096
+ ## Ameaças Específicas de Healthtech
1097
+
1098
+ | Ameaça | Descrição | Mitigação |
1099
+ |--------|-----------|-----------|
1100
+ | Acesso não Autorizado | Outro médico lê prontuário | RBAC por especialidade, audit |
1101
+ | Adulteração de Histórico | Alterar resultado de exame | Blockchain/assinatura digital |
1102
+ | Vazamento de Dados | Exposição de histórico médico | Criptografia, isolamento de rede |
1103
+ | Negação de Diagnóstico | Paciente nega consentimento | Digital signature + timestamp |
1104
+ | Indisponibilidade | Sistema cai durante consulta | Backup em tempo real, SLA 99.95% |
1105
+ | Privilégio Elevado | Admin lê dados de qualquer paciente | Segregação de funções, logging |`;
1106
+ }
1107
+ return `# 🛡️ Template: Threat Model (STRIDE)
1108
+
1109
+ > Use para features que lidam com dados sensíveis, pagamentos, autenticação.
1110
+
1111
+ ---
1112
+
1113
+ ## Feature: ${featureName}
1114
+
1115
+ ### Atores e Assets
1116
+
1117
+ | Ator | Nível de Confiança | Assets que Acessa |
1118
+ |------|-------------------|------------------|
1119
+ ${actors}
1120
+
1121
+ ---
1122
+
1123
+ ### Análise STRIDE
1124
+
1125
+ | Categoria | Ameaça | Probabilidade | Impacto | Mitigação |
1126
+ |-----------|--------|-------------|---------|-----------|
1127
+ | **S**poofing | Identidade falsa / autenticação fraca | M | A | MFA, JWT assinado, validação gov |
1128
+ | **T**ampering | Alteração de dados em trânsito/repouso | M | A | HTTPS, assinatura digital, checksums |
1129
+ | **R**epudiation | Negar ação realizada | M | A | Audit log detalhado com timestamp |
1130
+ | **I**nformation Disclosure | Vazamento de dados sensíveis | A | A | Criptografia AES-256, LGPD compliance |
1131
+ | **D**enial of Service | Serviço indisponível (DDoS, travamento) | M | A | Rate limiting, WAF, scaling automático |
1132
+ | **E**levation of Privilege | Escalar permissão (user → admin) | M | A | RBAC granular, segregação de funções |
1133
+
1134
+ ---
1135
+
1136
+ ### Dados Sensíveis
1137
+
1138
+ | Dado | Classificação | Proteção |
1139
+ |------|-------------|----------|
1140
+ ${sensitiveData}
1141
+
1142
+ ---
1143
+
1144
+ ### Conformidade e Requisitos Regulatórios
1145
+
1146
+ ${compliance.length > 0
1147
+ ? `| Regulamento | Aplicável | Verificação |
1148
+ |-------------|-----------|-------------|
1149
+ ${compliance.map((c) => `| ${c.name} | Sim | ${c.mandatoryChecks[0] || 'Auditoria'} |`).join('\n')}`
1150
+ : `| Regulamento | Aplicável | Verificação |
1151
+ |-------------|-----------|-------------|
1152
+ | LGPD (dados pessoais) | Depende | Consentimento, direito ao esquecimento |
1153
+ | Conformidade de Dados | Depende | Criptografia, HTTPS, audit logs |`}
1154
+
1155
+ ---
1156
+
1157
+ ### Checklist de Segurança
1158
+
1159
+ \`\`\`
1160
+ □ Input validado e sanitizado
1161
+ □ Output encodado (XSS prevention)
1162
+ □ Queries parametrizadas (SQL injection)
1163
+ □ Autenticação obrigatória (MFA quando sensível)
1164
+ □ Autorização por role/permission (RBAC)
1165
+ □ Dados sensíveis criptografados at rest (AES-256)
1166
+ □ Dados sensíveis criptografados in transit (TLS 1.2+)
1167
+ □ Rate limiting implementado
1168
+ □ Audit log para ações sensíveis (timestamp + usuário)
1169
+ □ Secrets em variáveis de ambiente (não hardcoded)
1170
+ □ Consentimento e transparência (LGPD/GDPR)
1171
+ □ Testes de penetração agendados
1172
+ \`\`\`
1173
+ ${domainSpecificThreats}
1174
+ `;
1175
+ }
1176
+ //# sourceMappingURL=index.js.map