opencode-telos 1.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 (568) hide show
  1. package/README.md +927 -0
  2. package/dist/code-intelligence/analyzer.d.ts +9 -0
  3. package/dist/code-intelligence/analyzer.d.ts.map +1 -0
  4. package/dist/code-intelligence/analyzer.js +321 -0
  5. package/dist/code-intelligence/analyzer.js.map +1 -0
  6. package/dist/code-intelligence/ast/cache.d.ts +16 -0
  7. package/dist/code-intelligence/ast/cache.d.ts.map +1 -0
  8. package/dist/code-intelligence/ast/cache.js +44 -0
  9. package/dist/code-intelligence/ast/cache.js.map +1 -0
  10. package/dist/code-intelligence/ast/common.d.ts +8 -0
  11. package/dist/code-intelligence/ast/common.d.ts.map +1 -0
  12. package/dist/code-intelligence/ast/common.js +42 -0
  13. package/dist/code-intelligence/ast/common.js.map +1 -0
  14. package/dist/code-intelligence/ast/component.d.ts +10 -0
  15. package/dist/code-intelligence/ast/component.d.ts.map +1 -0
  16. package/dist/code-intelligence/ast/component.js +38 -0
  17. package/dist/code-intelligence/ast/component.js.map +1 -0
  18. package/dist/code-intelligence/ast/fallback.d.ts +9 -0
  19. package/dist/code-intelligence/ast/fallback.d.ts.map +1 -0
  20. package/dist/code-intelligence/ast/fallback.js +38 -0
  21. package/dist/code-intelligence/ast/fallback.js.map +1 -0
  22. package/dist/code-intelligence/ast/index.d.ts +5 -0
  23. package/dist/code-intelligence/ast/index.d.ts.map +1 -0
  24. package/dist/code-intelligence/ast/index.js +5 -0
  25. package/dist/code-intelligence/ast/index.js.map +1 -0
  26. package/dist/code-intelligence/ast/ir.d.ts +72 -0
  27. package/dist/code-intelligence/ast/ir.d.ts.map +1 -0
  28. package/dist/code-intelligence/ast/ir.js +2 -0
  29. package/dist/code-intelligence/ast/ir.js.map +1 -0
  30. package/dist/code-intelligence/ast/metrics.d.ts +25 -0
  31. package/dist/code-intelligence/ast/metrics.d.ts.map +1 -0
  32. package/dist/code-intelligence/ast/metrics.js +38 -0
  33. package/dist/code-intelligence/ast/metrics.js.map +1 -0
  34. package/dist/code-intelligence/ast/registry.d.ts +5 -0
  35. package/dist/code-intelligence/ast/registry.d.ts.map +1 -0
  36. package/dist/code-intelligence/ast/registry.js +22 -0
  37. package/dist/code-intelligence/ast/registry.js.map +1 -0
  38. package/dist/code-intelligence/ast/tree-sitter.d.ts +8 -0
  39. package/dist/code-intelligence/ast/tree-sitter.d.ts.map +1 -0
  40. package/dist/code-intelligence/ast/tree-sitter.js +247 -0
  41. package/dist/code-intelligence/ast/tree-sitter.js.map +1 -0
  42. package/dist/code-intelligence/ast/typescript.d.ts +8 -0
  43. package/dist/code-intelligence/ast/typescript.d.ts.map +1 -0
  44. package/dist/code-intelligence/ast/typescript.js +147 -0
  45. package/dist/code-intelligence/ast/typescript.js.map +1 -0
  46. package/dist/index.d.ts +10 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +18 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/mcp/server.d.ts +27 -0
  51. package/dist/mcp/server.d.ts.map +1 -0
  52. package/dist/mcp/server.js +67 -0
  53. package/dist/mcp/server.js.map +1 -0
  54. package/dist/opencode/hooks.d.ts +9 -0
  55. package/dist/opencode/hooks.d.ts.map +1 -0
  56. package/dist/opencode/hooks.js +583 -0
  57. package/dist/opencode/hooks.js.map +1 -0
  58. package/dist/opencode/router/categories.d.ts +31 -0
  59. package/dist/opencode/router/categories.d.ts.map +1 -0
  60. package/dist/opencode/router/categories.js +165 -0
  61. package/dist/opencode/router/categories.js.map +1 -0
  62. package/dist/opencode/router/embeddings.d.ts +41 -0
  63. package/dist/opencode/router/embeddings.d.ts.map +1 -0
  64. package/dist/opencode/router/embeddings.js +136 -0
  65. package/dist/opencode/router/embeddings.js.map +1 -0
  66. package/dist/opencode/router/graph-state-snapshot.d.ts +35 -0
  67. package/dist/opencode/router/graph-state-snapshot.d.ts.map +1 -0
  68. package/dist/opencode/router/graph-state-snapshot.js +129 -0
  69. package/dist/opencode/router/graph-state-snapshot.js.map +1 -0
  70. package/dist/opencode/router/index.d.ts +21 -0
  71. package/dist/opencode/router/index.d.ts.map +1 -0
  72. package/dist/opencode/router/index.js +23 -0
  73. package/dist/opencode/router/index.js.map +1 -0
  74. package/dist/opencode/router/intent-classifier.d.ts +35 -0
  75. package/dist/opencode/router/intent-classifier.d.ts.map +1 -0
  76. package/dist/opencode/router/intent-classifier.js +108 -0
  77. package/dist/opencode/router/intent-classifier.js.map +1 -0
  78. package/dist/opencode/router/semantic-nudge.d.ts +42 -0
  79. package/dist/opencode/router/semantic-nudge.d.ts.map +1 -0
  80. package/dist/opencode/router/semantic-nudge.js +73 -0
  81. package/dist/opencode/router/semantic-nudge.js.map +1 -0
  82. package/dist/opencode/router/state-gate.d.ts +25 -0
  83. package/dist/opencode/router/state-gate.d.ts.map +1 -0
  84. package/dist/opencode/router/state-gate.js +178 -0
  85. package/dist/opencode/router/state-gate.js.map +1 -0
  86. package/dist/opencode/router/tool-embeddings.d.ts +36 -0
  87. package/dist/opencode/router/tool-embeddings.d.ts.map +1 -0
  88. package/dist/opencode/router/tool-embeddings.js +140 -0
  89. package/dist/opencode/router/tool-embeddings.js.map +1 -0
  90. package/dist/opencode/router/tool-registry.d.ts +45 -0
  91. package/dist/opencode/router/tool-registry.d.ts.map +1 -0
  92. package/dist/opencode/router/tool-registry.js +103 -0
  93. package/dist/opencode/router/tool-registry.js.map +1 -0
  94. package/dist/opencode/router/tool-taxonomy.d.ts +51 -0
  95. package/dist/opencode/router/tool-taxonomy.d.ts.map +1 -0
  96. package/dist/opencode/router/tool-taxonomy.js +250 -0
  97. package/dist/opencode/router/tool-taxonomy.js.map +1 -0
  98. package/dist/opencode/router/tools-composite.d.ts +21 -0
  99. package/dist/opencode/router/tools-composite.d.ts.map +1 -0
  100. package/dist/opencode/router/tools-composite.js +684 -0
  101. package/dist/opencode/router/tools-composite.js.map +1 -0
  102. package/dist/opencode/shell-hooks.d.ts +7 -0
  103. package/dist/opencode/shell-hooks.d.ts.map +1 -0
  104. package/dist/opencode/shell-hooks.js +96 -0
  105. package/dist/opencode/shell-hooks.js.map +1 -0
  106. package/dist/opencode/system-prompt.d.ts +10 -0
  107. package/dist/opencode/system-prompt.d.ts.map +1 -0
  108. package/dist/opencode/system-prompt.js +600 -0
  109. package/dist/opencode/system-prompt.js.map +1 -0
  110. package/dist/opencode/tools.d.ts +8 -0
  111. package/dist/opencode/tools.d.ts.map +1 -0
  112. package/dist/opencode/tools.js +3731 -0
  113. package/dist/opencode/tools.js.map +1 -0
  114. package/dist/opencode/workflows/chains.d.ts +52 -0
  115. package/dist/opencode/workflows/chains.d.ts.map +1 -0
  116. package/dist/opencode/workflows/chains.js +170 -0
  117. package/dist/opencode/workflows/chains.js.map +1 -0
  118. package/dist/opencode/workflows/executor.d.ts +52 -0
  119. package/dist/opencode/workflows/executor.d.ts.map +1 -0
  120. package/dist/opencode/workflows/executor.js +130 -0
  121. package/dist/opencode/workflows/executor.js.map +1 -0
  122. package/dist/opencode/workflows/index.d.ts +14 -0
  123. package/dist/opencode/workflows/index.d.ts.map +1 -0
  124. package/dist/opencode/workflows/index.js +15 -0
  125. package/dist/opencode/workflows/index.js.map +1 -0
  126. package/dist/opencode/workflows/tools-workflow.d.ts +24 -0
  127. package/dist/opencode/workflows/tools-workflow.d.ts.map +1 -0
  128. package/dist/opencode/workflows/tools-workflow.js +85 -0
  129. package/dist/opencode/workflows/tools-workflow.js.map +1 -0
  130. package/dist/opencode/workflows/types.d.ts +32 -0
  131. package/dist/opencode/workflows/types.d.ts.map +1 -0
  132. package/dist/opencode/workflows/types.js +13 -0
  133. package/dist/opencode/workflows/types.js.map +1 -0
  134. package/dist/sdd/analysis/compliance.d.ts +30 -0
  135. package/dist/sdd/analysis/compliance.d.ts.map +1 -0
  136. package/dist/sdd/analysis/compliance.js +251 -0
  137. package/dist/sdd/analysis/compliance.js.map +1 -0
  138. package/dist/sdd/analysis/scalability.d.ts +15 -0
  139. package/dist/sdd/analysis/scalability.d.ts.map +1 -0
  140. package/dist/sdd/analysis/scalability.js +72 -0
  141. package/dist/sdd/analysis/scalability.js.map +1 -0
  142. package/dist/sdd/analysis/security.d.ts +25 -0
  143. package/dist/sdd/analysis/security.d.ts.map +1 -0
  144. package/dist/sdd/analysis/security.js +94 -0
  145. package/dist/sdd/analysis/security.js.map +1 -0
  146. package/dist/sdd/brownfield/scanner.d.ts +31 -0
  147. package/dist/sdd/brownfield/scanner.d.ts.map +1 -0
  148. package/dist/sdd/brownfield/scanner.js +228 -0
  149. package/dist/sdd/brownfield/scanner.js.map +1 -0
  150. package/dist/sdd/cache/manager.d.ts +237 -0
  151. package/dist/sdd/cache/manager.d.ts.map +1 -0
  152. package/dist/sdd/cache/manager.js +770 -0
  153. package/dist/sdd/cache/manager.js.map +1 -0
  154. package/dist/sdd/cache/snapshot-store.d.ts +39 -0
  155. package/dist/sdd/cache/snapshot-store.d.ts.map +1 -0
  156. package/dist/sdd/cache/snapshot-store.js +156 -0
  157. package/dist/sdd/cache/snapshot-store.js.map +1 -0
  158. package/dist/sdd/changes/manager.d.ts +58 -0
  159. package/dist/sdd/changes/manager.d.ts.map +1 -0
  160. package/dist/sdd/changes/manager.js +235 -0
  161. package/dist/sdd/changes/manager.js.map +1 -0
  162. package/dist/sdd/cicd/generators.d.ts +16 -0
  163. package/dist/sdd/cicd/generators.d.ts.map +1 -0
  164. package/dist/sdd/cicd/generators.js +1042 -0
  165. package/dist/sdd/cicd/generators.js.map +1 -0
  166. package/dist/sdd/code-quality/complexity.d.ts +38 -0
  167. package/dist/sdd/code-quality/complexity.d.ts.map +1 -0
  168. package/dist/sdd/code-quality/complexity.js +161 -0
  169. package/dist/sdd/code-quality/complexity.js.map +1 -0
  170. package/dist/sdd/code-quality/conventions.d.ts +33 -0
  171. package/dist/sdd/code-quality/conventions.d.ts.map +1 -0
  172. package/dist/sdd/code-quality/conventions.js +193 -0
  173. package/dist/sdd/code-quality/conventions.js.map +1 -0
  174. package/dist/sdd/code-quality/dependencies.d.ts +27 -0
  175. package/dist/sdd/code-quality/dependencies.d.ts.map +1 -0
  176. package/dist/sdd/code-quality/dependencies.js +142 -0
  177. package/dist/sdd/code-quality/dependencies.js.map +1 -0
  178. package/dist/sdd/code-quality/import-analyzer.d.ts +49 -0
  179. package/dist/sdd/code-quality/import-analyzer.d.ts.map +1 -0
  180. package/dist/sdd/code-quality/import-analyzer.js +213 -0
  181. package/dist/sdd/code-quality/import-analyzer.js.map +1 -0
  182. package/dist/sdd/code-quality/metrics.d.ts +35 -0
  183. package/dist/sdd/code-quality/metrics.d.ts.map +1 -0
  184. package/dist/sdd/code-quality/metrics.js +172 -0
  185. package/dist/sdd/code-quality/metrics.js.map +1 -0
  186. package/dist/sdd/code-quality/smells.d.ts +38 -0
  187. package/dist/sdd/code-quality/smells.d.ts.map +1 -0
  188. package/dist/sdd/code-quality/smells.js +319 -0
  189. package/dist/sdd/code-quality/smells.js.map +1 -0
  190. package/dist/sdd/code-quality/symbol-parser.d.ts +28 -0
  191. package/dist/sdd/code-quality/symbol-parser.d.ts.map +1 -0
  192. package/dist/sdd/code-quality/symbol-parser.js +230 -0
  193. package/dist/sdd/code-quality/symbol-parser.js.map +1 -0
  194. package/dist/sdd/code-quality/usage-tracker.d.ts +59 -0
  195. package/dist/sdd/code-quality/usage-tracker.d.ts.map +1 -0
  196. package/dist/sdd/code-quality/usage-tracker.js +402 -0
  197. package/dist/sdd/code-quality/usage-tracker.js.map +1 -0
  198. package/dist/sdd/code-quality/utils.d.ts +6 -0
  199. package/dist/sdd/code-quality/utils.d.ts.map +1 -0
  200. package/dist/sdd/code-quality/utils.js +14 -0
  201. package/dist/sdd/code-quality/utils.js.map +1 -0
  202. package/dist/sdd/codegen/generator.d.ts +42 -0
  203. package/dist/sdd/codegen/generator.d.ts.map +1 -0
  204. package/dist/sdd/codegen/generator.js +1023 -0
  205. package/dist/sdd/codegen/generator.js.map +1 -0
  206. package/dist/sdd/constitution/validator.d.ts +37 -0
  207. package/dist/sdd/constitution/validator.d.ts.map +1 -0
  208. package/dist/sdd/constitution/validator.js +192 -0
  209. package/dist/sdd/constitution/validator.js.map +1 -0
  210. package/dist/sdd/cost/estimator.d.ts +31 -0
  211. package/dist/sdd/cost/estimator.d.ts.map +1 -0
  212. package/dist/sdd/cost/estimator.js +92 -0
  213. package/dist/sdd/cost/estimator.js.map +1 -0
  214. package/dist/sdd/coverage/tracker.d.ts +47 -0
  215. package/dist/sdd/coverage/tracker.d.ts.map +1 -0
  216. package/dist/sdd/coverage/tracker.js +251 -0
  217. package/dist/sdd/coverage/tracker.js.map +1 -0
  218. package/dist/sdd/disaster/recovery.d.ts +11 -0
  219. package/dist/sdd/disaster/recovery.d.ts.map +1 -0
  220. package/dist/sdd/disaster/recovery.js +55 -0
  221. package/dist/sdd/disaster/recovery.js.map +1 -0
  222. package/dist/sdd/discovery/adaptive.d.ts +14 -0
  223. package/dist/sdd/discovery/adaptive.d.ts.map +1 -0
  224. package/dist/sdd/discovery/adaptive.js +145 -0
  225. package/dist/sdd/discovery/adaptive.js.map +1 -0
  226. package/dist/sdd/discovery/briefing-analyzer.d.ts +66 -0
  227. package/dist/sdd/discovery/briefing-analyzer.d.ts.map +1 -0
  228. package/dist/sdd/discovery/briefing-analyzer.js +672 -0
  229. package/dist/sdd/discovery/briefing-analyzer.js.map +1 -0
  230. package/dist/sdd/discovery/briefing.d.ts +109 -0
  231. package/dist/sdd/discovery/briefing.d.ts.map +1 -0
  232. package/dist/sdd/discovery/briefing.js +617 -0
  233. package/dist/sdd/discovery/briefing.js.map +1 -0
  234. package/dist/sdd/discovery/graph-builder.d.ts +10 -0
  235. package/dist/sdd/discovery/graph-builder.d.ts.map +1 -0
  236. package/dist/sdd/discovery/graph-builder.js +510 -0
  237. package/dist/sdd/discovery/graph-builder.js.map +1 -0
  238. package/dist/sdd/documentation/generator.d.ts +7 -0
  239. package/dist/sdd/documentation/generator.d.ts.map +1 -0
  240. package/dist/sdd/documentation/generator.js +119 -0
  241. package/dist/sdd/documentation/generator.js.map +1 -0
  242. package/dist/sdd/domain/types.d.ts +460 -0
  243. package/dist/sdd/domain/types.d.ts.map +1 -0
  244. package/dist/sdd/domain/types.js +25 -0
  245. package/dist/sdd/domain/types.js.map +1 -0
  246. package/dist/sdd/drift/detector.d.ts +28 -0
  247. package/dist/sdd/drift/detector.d.ts.map +1 -0
  248. package/dist/sdd/drift/detector.js +379 -0
  249. package/dist/sdd/drift/detector.js.map +1 -0
  250. package/dist/sdd/drift/exclusion.d.ts +54 -0
  251. package/dist/sdd/drift/exclusion.d.ts.map +1 -0
  252. package/dist/sdd/drift/exclusion.js +179 -0
  253. package/dist/sdd/drift/exclusion.js.map +1 -0
  254. package/dist/sdd/drift/signals.d.ts +52 -0
  255. package/dist/sdd/drift/signals.d.ts.map +1 -0
  256. package/dist/sdd/drift/signals.js +470 -0
  257. package/dist/sdd/drift/signals.js.map +1 -0
  258. package/dist/sdd/enforcement/interceptor.d.ts +47 -0
  259. package/dist/sdd/enforcement/interceptor.d.ts.map +1 -0
  260. package/dist/sdd/enforcement/interceptor.js +365 -0
  261. package/dist/sdd/enforcement/interceptor.js.map +1 -0
  262. package/dist/sdd/enforcement/workflow-tracker.d.ts +66 -0
  263. package/dist/sdd/enforcement/workflow-tracker.d.ts.map +1 -0
  264. package/dist/sdd/enforcement/workflow-tracker.js +229 -0
  265. package/dist/sdd/enforcement/workflow-tracker.js.map +1 -0
  266. package/dist/sdd/graph/engine.d.ts +44 -0
  267. package/dist/sdd/graph/engine.d.ts.map +1 -0
  268. package/dist/sdd/graph/engine.js +203 -0
  269. package/dist/sdd/graph/engine.js.map +1 -0
  270. package/dist/sdd/graph/index.d.ts +160 -0
  271. package/dist/sdd/graph/index.d.ts.map +1 -0
  272. package/dist/sdd/graph/index.js +624 -0
  273. package/dist/sdd/graph/index.js.map +1 -0
  274. package/dist/sdd/graph/integrity-guard.d.ts +129 -0
  275. package/dist/sdd/graph/integrity-guard.d.ts.map +1 -0
  276. package/dist/sdd/graph/integrity-guard.js +263 -0
  277. package/dist/sdd/graph/integrity-guard.js.map +1 -0
  278. package/dist/sdd/graph/integrity.d.ts +79 -0
  279. package/dist/sdd/graph/integrity.d.ts.map +1 -0
  280. package/dist/sdd/graph/integrity.js +462 -0
  281. package/dist/sdd/graph/integrity.js.map +1 -0
  282. package/dist/sdd/graph/pruner.d.ts +27 -0
  283. package/dist/sdd/graph/pruner.d.ts.map +1 -0
  284. package/dist/sdd/graph/pruner.js +203 -0
  285. package/dist/sdd/graph/pruner.js.map +1 -0
  286. package/dist/sdd/graph/traverse.d.ts +43 -0
  287. package/dist/sdd/graph/traverse.d.ts.map +1 -0
  288. package/dist/sdd/graph/traverse.js +265 -0
  289. package/dist/sdd/graph/traverse.js.map +1 -0
  290. package/dist/sdd/incidents/manager.d.ts +10 -0
  291. package/dist/sdd/incidents/manager.d.ts.map +1 -0
  292. package/dist/sdd/incidents/manager.js +63 -0
  293. package/dist/sdd/incidents/manager.js.map +1 -0
  294. package/dist/sdd/knowledge/transfer.d.ts +24 -0
  295. package/dist/sdd/knowledge/transfer.d.ts.map +1 -0
  296. package/dist/sdd/knowledge/transfer.js +94 -0
  297. package/dist/sdd/knowledge/transfer.js.map +1 -0
  298. package/dist/sdd/migrations/fixes.d.ts +2 -0
  299. package/dist/sdd/migrations/fixes.d.ts.map +1 -0
  300. package/dist/sdd/migrations/fixes.js +159 -0
  301. package/dist/sdd/migrations/fixes.js.map +1 -0
  302. package/dist/sdd/migrations/index.d.ts +2 -0
  303. package/dist/sdd/migrations/index.d.ts.map +1 -0
  304. package/dist/sdd/migrations/index.js +5 -0
  305. package/dist/sdd/migrations/index.js.map +1 -0
  306. package/dist/sdd/migrations/migration-runner.d.ts +41 -0
  307. package/dist/sdd/migrations/migration-runner.d.ts.map +1 -0
  308. package/dist/sdd/migrations/migration-runner.js +91 -0
  309. package/dist/sdd/migrations/migration-runner.js.map +1 -0
  310. package/dist/sdd/monitoring/setup.d.ts +40 -0
  311. package/dist/sdd/monitoring/setup.d.ts.map +1 -0
  312. package/dist/sdd/monitoring/setup.js +177 -0
  313. package/dist/sdd/monitoring/setup.js.map +1 -0
  314. package/dist/sdd/monitoring/telemetry.d.ts +18 -0
  315. package/dist/sdd/monitoring/telemetry.d.ts.map +1 -0
  316. package/dist/sdd/monitoring/telemetry.js +37 -0
  317. package/dist/sdd/monitoring/telemetry.js.map +1 -0
  318. package/dist/sdd/patterns/anti-patterns.d.ts +21 -0
  319. package/dist/sdd/patterns/anti-patterns.d.ts.map +1 -0
  320. package/dist/sdd/patterns/anti-patterns.js +286 -0
  321. package/dist/sdd/patterns/anti-patterns.js.map +1 -0
  322. package/dist/sdd/patterns/ast-clones.d.ts +23 -0
  323. package/dist/sdd/patterns/ast-clones.d.ts.map +1 -0
  324. package/dist/sdd/patterns/ast-clones.js +171 -0
  325. package/dist/sdd/patterns/ast-clones.js.map +1 -0
  326. package/dist/sdd/patterns/config-drift.d.ts +16 -0
  327. package/dist/sdd/patterns/config-drift.d.ts.map +1 -0
  328. package/dist/sdd/patterns/config-drift.js +322 -0
  329. package/dist/sdd/patterns/config-drift.js.map +1 -0
  330. package/dist/sdd/patterns/contradictions.d.ts +38 -0
  331. package/dist/sdd/patterns/contradictions.d.ts.map +1 -0
  332. package/dist/sdd/patterns/contradictions.js +237 -0
  333. package/dist/sdd/patterns/contradictions.js.map +1 -0
  334. package/dist/sdd/patterns/learner.d.ts +49 -0
  335. package/dist/sdd/patterns/learner.d.ts.map +1 -0
  336. package/dist/sdd/patterns/learner.js +226 -0
  337. package/dist/sdd/patterns/learner.js.map +1 -0
  338. package/dist/sdd/permissions/access.d.ts +69 -0
  339. package/dist/sdd/permissions/access.d.ts.map +1 -0
  340. package/dist/sdd/permissions/access.js +333 -0
  341. package/dist/sdd/permissions/access.js.map +1 -0
  342. package/dist/sdd/persistence/repository.d.ts +60 -0
  343. package/dist/sdd/persistence/repository.d.ts.map +1 -0
  344. package/dist/sdd/persistence/repository.js +96 -0
  345. package/dist/sdd/persistence/repository.js.map +1 -0
  346. package/dist/sdd/persistence/sqlite.d.ts +122 -0
  347. package/dist/sdd/persistence/sqlite.d.ts.map +1 -0
  348. package/dist/sdd/persistence/sqlite.js +602 -0
  349. package/dist/sdd/persistence/sqlite.js.map +1 -0
  350. package/dist/sdd/persistence/yaml.d.ts +41 -0
  351. package/dist/sdd/persistence/yaml.d.ts.map +1 -0
  352. package/dist/sdd/persistence/yaml.js +382 -0
  353. package/dist/sdd/persistence/yaml.js.map +1 -0
  354. package/dist/sdd/promises/classifier.d.ts +48 -0
  355. package/dist/sdd/promises/classifier.d.ts.map +1 -0
  356. package/dist/sdd/promises/classifier.js +215 -0
  357. package/dist/sdd/promises/classifier.js.map +1 -0
  358. package/dist/sdd/promises/tracker.d.ts +20 -0
  359. package/dist/sdd/promises/tracker.d.ts.map +1 -0
  360. package/dist/sdd/promises/tracker.js +204 -0
  361. package/dist/sdd/promises/tracker.js.map +1 -0
  362. package/dist/sdd/quality/scorer.d.ts +44 -0
  363. package/dist/sdd/quality/scorer.d.ts.map +1 -0
  364. package/dist/sdd/quality/scorer.js +216 -0
  365. package/dist/sdd/quality/scorer.js.map +1 -0
  366. package/dist/sdd/rollback/manager.d.ts +45 -0
  367. package/dist/sdd/rollback/manager.d.ts.map +1 -0
  368. package/dist/sdd/rollback/manager.js +266 -0
  369. package/dist/sdd/rollback/manager.js.map +1 -0
  370. package/dist/sdd/session/handoff.d.ts +52 -0
  371. package/dist/sdd/session/handoff.d.ts.map +1 -0
  372. package/dist/sdd/session/handoff.js +264 -0
  373. package/dist/sdd/session/handoff.js.map +1 -0
  374. package/dist/sdd/sla/tracker.d.ts +11 -0
  375. package/dist/sdd/sla/tracker.d.ts.map +1 -0
  376. package/dist/sdd/sla/tracker.js +52 -0
  377. package/dist/sdd/sla/tracker.js.map +1 -0
  378. package/dist/sdd/sync/git-sync.d.ts +61 -0
  379. package/dist/sdd/sync/git-sync.d.ts.map +1 -0
  380. package/dist/sdd/sync/git-sync.js +297 -0
  381. package/dist/sdd/sync/git-sync.js.map +1 -0
  382. package/dist/sdd/toggle/state.d.ts +8 -0
  383. package/dist/sdd/toggle/state.d.ts.map +1 -0
  384. package/dist/sdd/toggle/state.js +32 -0
  385. package/dist/sdd/toggle/state.js.map +1 -0
  386. package/dist/sdd/transactions/manager.d.ts +12 -0
  387. package/dist/sdd/transactions/manager.d.ts.map +1 -0
  388. package/dist/sdd/transactions/manager.js +80 -0
  389. package/dist/sdd/transactions/manager.js.map +1 -0
  390. package/dist/sdd/validation/coverage-index.d.ts +117 -0
  391. package/dist/sdd/validation/coverage-index.d.ts.map +1 -0
  392. package/dist/sdd/validation/coverage-index.js +251 -0
  393. package/dist/sdd/validation/coverage-index.js.map +1 -0
  394. package/dist/sdd/validation/executable.d.ts +26 -0
  395. package/dist/sdd/validation/executable.d.ts.map +1 -0
  396. package/dist/sdd/validation/executable.js +122 -0
  397. package/dist/sdd/validation/executable.js.map +1 -0
  398. package/dist/sdd/validation/smart-validator.d.ts +53 -0
  399. package/dist/sdd/validation/smart-validator.d.ts.map +1 -0
  400. package/dist/sdd/validation/smart-validator.js +347 -0
  401. package/dist/sdd/validation/smart-validator.js.map +1 -0
  402. package/dist/sdd/validation/validator.d.ts +39 -0
  403. package/dist/sdd/validation/validator.d.ts.map +1 -0
  404. package/dist/sdd/validation/validator.js +512 -0
  405. package/dist/sdd/validation/validator.js.map +1 -0
  406. package/dist/sdd/workflow/exporter.d.ts +36 -0
  407. package/dist/sdd/workflow/exporter.d.ts.map +1 -0
  408. package/dist/sdd/workflow/exporter.js +112 -0
  409. package/dist/sdd/workflow/exporter.js.map +1 -0
  410. package/dist/sdd/workflows/ab-testing.d.ts +18 -0
  411. package/dist/sdd/workflows/ab-testing.d.ts.map +1 -0
  412. package/dist/sdd/workflows/ab-testing.js +67 -0
  413. package/dist/sdd/workflows/ab-testing.js.map +1 -0
  414. package/dist/sdd/workflows/bug-fix.d.ts +13 -0
  415. package/dist/sdd/workflows/bug-fix.d.ts.map +1 -0
  416. package/dist/sdd/workflows/bug-fix.js +65 -0
  417. package/dist/sdd/workflows/bug-fix.js.map +1 -0
  418. package/dist/sdd/workflows/data-migration.d.ts +14 -0
  419. package/dist/sdd/workflows/data-migration.d.ts.map +1 -0
  420. package/dist/sdd/workflows/data-migration.js +68 -0
  421. package/dist/sdd/workflows/data-migration.js.map +1 -0
  422. package/dist/sdd/workflows/deprecation.d.ts +15 -0
  423. package/dist/sdd/workflows/deprecation.d.ts.map +1 -0
  424. package/dist/sdd/workflows/deprecation.js +68 -0
  425. package/dist/sdd/workflows/deprecation.js.map +1 -0
  426. package/dist/sdd/workflows/feature-flags.d.ts +14 -0
  427. package/dist/sdd/workflows/feature-flags.d.ts.map +1 -0
  428. package/dist/sdd/workflows/feature-flags.js +73 -0
  429. package/dist/sdd/workflows/feature-flags.js.map +1 -0
  430. package/dist/sdd/workflows/hotfix.d.ts +13 -0
  431. package/dist/sdd/workflows/hotfix.d.ts.map +1 -0
  432. package/dist/sdd/workflows/hotfix.js +67 -0
  433. package/dist/sdd/workflows/hotfix.js.map +1 -0
  434. package/dist/sdd/workflows/multi-tenancy.d.ts +13 -0
  435. package/dist/sdd/workflows/multi-tenancy.d.ts.map +1 -0
  436. package/dist/sdd/workflows/multi-tenancy.js +68 -0
  437. package/dist/sdd/workflows/multi-tenancy.js.map +1 -0
  438. package/dist/sdd/workflows/onboarding.d.ts +7 -0
  439. package/dist/sdd/workflows/onboarding.d.ts.map +1 -0
  440. package/dist/sdd/workflows/onboarding.js +43 -0
  441. package/dist/sdd/workflows/onboarding.js.map +1 -0
  442. package/dist/sdd/workflows/refactoring.d.ts +14 -0
  443. package/dist/sdd/workflows/refactoring.d.ts.map +1 -0
  444. package/dist/sdd/workflows/refactoring.js +73 -0
  445. package/dist/sdd/workflows/refactoring.js.map +1 -0
  446. package/dist/server/events.d.ts +64 -0
  447. package/dist/server/events.d.ts.map +1 -0
  448. package/dist/server/events.js +149 -0
  449. package/dist/server/events.js.map +1 -0
  450. package/dist/server/server.d.ts +33 -0
  451. package/dist/server/server.d.ts.map +1 -0
  452. package/dist/server/server.js +1019 -0
  453. package/dist/server/server.js.map +1 -0
  454. package/marketplace.json +39 -0
  455. package/package.json +65 -0
  456. package/src/code-intelligence/analyzer.ts +350 -0
  457. package/src/code-intelligence/ast/cache.ts +61 -0
  458. package/src/code-intelligence/ast/common.ts +62 -0
  459. package/src/code-intelligence/ast/component.ts +39 -0
  460. package/src/code-intelligence/ast/fallback.ts +44 -0
  461. package/src/code-intelligence/ast/index.ts +4 -0
  462. package/src/code-intelligence/ast/ir.ts +91 -0
  463. package/src/code-intelligence/ast/metrics.ts +65 -0
  464. package/src/code-intelligence/ast/registry.ts +28 -0
  465. package/src/code-intelligence/ast/tree-sitter.ts +226 -0
  466. package/src/code-intelligence/ast/typescript.ts +140 -0
  467. package/src/index.ts +22 -0
  468. package/src/mcp/server.ts +77 -0
  469. package/src/opencode/hooks.ts +728 -0
  470. package/src/opencode/router/categories.ts +192 -0
  471. package/src/opencode/router/embeddings.ts +149 -0
  472. package/src/opencode/router/graph-state-snapshot.ts +163 -0
  473. package/src/opencode/router/index.ts +44 -0
  474. package/src/opencode/router/intent-classifier.ts +140 -0
  475. package/src/opencode/router/semantic-nudge.ts +89 -0
  476. package/src/opencode/router/state-gate.ts +192 -0
  477. package/src/opencode/router/tool-embeddings.ts +162 -0
  478. package/src/opencode/router/tool-registry.ts +135 -0
  479. package/src/opencode/router/tool-taxonomy.ts +284 -0
  480. package/src/opencode/router/tools-composite.ts +685 -0
  481. package/src/opencode/shell-hooks.ts +115 -0
  482. package/src/opencode/system-prompt.ts +617 -0
  483. package/src/opencode/tools.ts +4102 -0
  484. package/src/opencode/workflows/chains.ts +205 -0
  485. package/src/opencode/workflows/executor.ts +172 -0
  486. package/src/opencode/workflows/index.ts +21 -0
  487. package/src/opencode/workflows/tools-workflow.ts +91 -0
  488. package/src/opencode/workflows/types.ts +42 -0
  489. package/src/sdd/analysis/compliance.ts +279 -0
  490. package/src/sdd/analysis/scalability.ts +97 -0
  491. package/src/sdd/analysis/security.ts +135 -0
  492. package/src/sdd/brownfield/scanner.ts +276 -0
  493. package/src/sdd/cache/manager.ts +899 -0
  494. package/src/sdd/cache/snapshot-store.ts +185 -0
  495. package/src/sdd/changes/manager.ts +326 -0
  496. package/src/sdd/cicd/generators.ts +1095 -0
  497. package/src/sdd/code-quality/complexity.ts +235 -0
  498. package/src/sdd/code-quality/conventions.ts +220 -0
  499. package/src/sdd/code-quality/dependencies.ts +203 -0
  500. package/src/sdd/code-quality/import-analyzer.ts +294 -0
  501. package/src/sdd/code-quality/metrics.ts +232 -0
  502. package/src/sdd/code-quality/smells.ts +415 -0
  503. package/src/sdd/code-quality/symbol-parser.ts +335 -0
  504. package/src/sdd/code-quality/usage-tracker.ts +527 -0
  505. package/src/sdd/code-quality/utils.ts +13 -0
  506. package/src/sdd/codegen/generator.ts +1181 -0
  507. package/src/sdd/constitution/validator.ts +253 -0
  508. package/src/sdd/cost/estimator.ts +147 -0
  509. package/src/sdd/coverage/tracker.ts +342 -0
  510. package/src/sdd/disaster/recovery.ts +79 -0
  511. package/src/sdd/discovery/adaptive.ts +167 -0
  512. package/src/sdd/discovery/briefing-analyzer.ts +802 -0
  513. package/src/sdd/discovery/briefing.ts +770 -0
  514. package/src/sdd/discovery/graph-builder.ts +598 -0
  515. package/src/sdd/documentation/generator.ts +158 -0
  516. package/src/sdd/domain/types.ts +658 -0
  517. package/src/sdd/drift/detector.ts +465 -0
  518. package/src/sdd/drift/exclusion.ts +223 -0
  519. package/src/sdd/drift/signals.ts +577 -0
  520. package/src/sdd/enforcement/interceptor.ts +444 -0
  521. package/src/sdd/enforcement/workflow-tracker.ts +263 -0
  522. package/src/sdd/graph/engine.ts +277 -0
  523. package/src/sdd/graph/index.ts +700 -0
  524. package/src/sdd/graph/integrity-guard.ts +348 -0
  525. package/src/sdd/graph/integrity.ts +628 -0
  526. package/src/sdd/graph/pruner.ts +221 -0
  527. package/src/sdd/graph/traverse.ts +331 -0
  528. package/src/sdd/incidents/manager.ts +87 -0
  529. package/src/sdd/knowledge/transfer.ts +140 -0
  530. package/src/sdd/migrations/fixes.ts +154 -0
  531. package/src/sdd/migrations/index.ts +14 -0
  532. package/src/sdd/migrations/migration-runner.ts +118 -0
  533. package/src/sdd/monitoring/setup.ts +237 -0
  534. package/src/sdd/monitoring/telemetry.ts +44 -0
  535. package/src/sdd/patterns/anti-patterns.ts +333 -0
  536. package/src/sdd/patterns/ast-clones.ts +214 -0
  537. package/src/sdd/patterns/config-drift.ts +346 -0
  538. package/src/sdd/patterns/contradictions.ts +323 -0
  539. package/src/sdd/patterns/learner.ts +266 -0
  540. package/src/sdd/permissions/access.ts +478 -0
  541. package/src/sdd/persistence/repository.ts +166 -0
  542. package/src/sdd/persistence/sqlite.ts +703 -0
  543. package/src/sdd/persistence/yaml.ts +409 -0
  544. package/src/sdd/promises/classifier.ts +253 -0
  545. package/src/sdd/promises/tracker.ts +258 -0
  546. package/src/sdd/quality/scorer.ts +263 -0
  547. package/src/sdd/rollback/manager.ts +361 -0
  548. package/src/sdd/session/handoff.ts +354 -0
  549. package/src/sdd/sla/tracker.ts +68 -0
  550. package/src/sdd/sync/git-sync.ts +401 -0
  551. package/src/sdd/toggle/state.ts +38 -0
  552. package/src/sdd/transactions/manager.ts +93 -0
  553. package/src/sdd/validation/coverage-index.ts +339 -0
  554. package/src/sdd/validation/executable.ts +127 -0
  555. package/src/sdd/validation/smart-validator.ts +470 -0
  556. package/src/sdd/validation/validator.ts +641 -0
  557. package/src/sdd/workflow/exporter.ts +169 -0
  558. package/src/sdd/workflows/ab-testing.ts +90 -0
  559. package/src/sdd/workflows/bug-fix.ts +81 -0
  560. package/src/sdd/workflows/data-migration.ts +86 -0
  561. package/src/sdd/workflows/deprecation.ts +87 -0
  562. package/src/sdd/workflows/feature-flags.ts +91 -0
  563. package/src/sdd/workflows/hotfix.ts +83 -0
  564. package/src/sdd/workflows/multi-tenancy.ts +84 -0
  565. package/src/sdd/workflows/onboarding.ts +82 -0
  566. package/src/sdd/workflows/refactoring.ts +90 -0
  567. package/src/server/events.ts +184 -0
  568. package/src/server/server.ts +1088 -0
@@ -0,0 +1,770 @@
1
+ import type { KnowledgeGraph, GapClassification } from "../domain/types.js"
2
+ import { addNode } from "../graph/engine.js"
3
+
4
+ export interface BriefingAnalysis {
5
+ known_facts: Record<string, string>
6
+ missing_information: MissingInfo[]
7
+ ambiguities: string[]
8
+ contradictions: string[]
9
+ inferred_entities: string[]
10
+ inferred_architecture: string[]
11
+ inferred_auth: string | null
12
+ domain_detected: string | null
13
+ tech_stack: DetectedTechStack
14
+ file_references: FileReference[]
15
+ }
16
+
17
+ /**
18
+ * Options for controlling briefing analysis scope.
19
+ */
20
+ export interface BriefingAnalysisOptions {
21
+ /** Only run these detection categories (e.g., ["tech", "domain", "entity"]). */
22
+ focusCategories?: string[]
23
+ /** Skip these detection categories. */
24
+ excludeCategories?: string[]
25
+ /** Skip these specific entity patterns. */
26
+ excludeEntities?: string[]
27
+ /** Skip these specific domain patterns. */
28
+ excludeDomains?: string[]
29
+ /** Additional entity patterns to detect. */
30
+ customEntities?: Array<{ pattern: string; name: string }>
31
+ /** Additional domain patterns to detect. */
32
+ customDomains?: Array<{ name: string; pattern: string }>
33
+ /** Cache for analysis results (briefing_hash → result). */
34
+ analysisCache?: Map<string, { result: BriefingAnalysis; timestamp: number }>
35
+ /** Hash of the briefing text to check cache validity. */
36
+ briefingHash?: string
37
+ }
38
+
39
+ export interface DetectedTechStack {
40
+ frontend: string | null
41
+ backend: string | null
42
+ database: string | null
43
+ auth: string | null
44
+ language: string | null
45
+ testing: string | null
46
+ other: string[]
47
+ }
48
+
49
+ export interface FileReference {
50
+ path: string
51
+ context: string
52
+ }
53
+
54
+ export interface MissingInfo {
55
+ category: string
56
+ description: string
57
+ classification: GapClassification
58
+ already_answered: boolean
59
+ question_for_user: QuestionForUser | null
60
+ }
61
+
62
+ export interface QuestionForUser {
63
+ question: string
64
+ header: string
65
+ options: Array<{ label: string; description: string }>
66
+ multiple?: boolean
67
+ }
68
+
69
+ export interface DiscoveryResult {
70
+ analysis: BriefingAnalysis
71
+ questions_for_agent: QuestionForUser[]
72
+ sufficient: boolean
73
+ summary: string
74
+ update_commands: UpdateCommand[]
75
+ }
76
+
77
+ export interface UpdateCommand {
78
+ type: "add_node" | "add_relationship" | "update_node"
79
+ node_type?: string
80
+ node_name?: string
81
+ metadata?: Record<string, unknown>
82
+ from?: string
83
+ to?: string
84
+ relationship_type?: string
85
+ }
86
+
87
+ export function analyzeBriefing(
88
+ briefing: string,
89
+ options?: BriefingAnalysisOptions,
90
+ ): BriefingAnalysis {
91
+ // Check cache first
92
+ if (options?.analysisCache && options.briefingHash) {
93
+ const cached = options.analysisCache.get(options.briefingHash)
94
+ if (cached && (Date.now() - cached.timestamp) < 300000) { // 5 min cache
95
+ return cached.result
96
+ }
97
+ }
98
+
99
+ const analysis: BriefingAnalysis = {
100
+ known_facts: {},
101
+ missing_information: [],
102
+ ambiguities: [],
103
+ contradictions: [],
104
+ inferred_entities: [],
105
+ inferred_architecture: [],
106
+ inferred_auth: null,
107
+ domain_detected: null,
108
+ tech_stack: { frontend: null, backend: null, database: null, auth: null, language: null, testing: null, other: [] },
109
+ file_references: [],
110
+ }
111
+
112
+ const shouldDetect = (category: string) => {
113
+ if (options?.excludeCategories?.includes(category)) return false
114
+ if (options?.focusCategories?.length && !options.focusCategories.includes(category)) return false
115
+ return true
116
+ }
117
+
118
+ // Extract @ file references
119
+ const fileRefPattern = /@([\w\-\.\/]+\.\w+)/g
120
+ let match: RegExpExecArray | null
121
+ while ((match = fileRefPattern.exec(briefing)) !== null) {
122
+ analysis.file_references.push({ path: match[1], context: extractContextAround(briefing, match.index) })
123
+ }
124
+
125
+ // Detect tech stack - comprehensive patterns
126
+ const techDetections: Array<{ key: string; patterns: RegExp[]; category: keyof DetectedTechStack }> = [
127
+ // Frontend
128
+ { key: "React", patterns: [/react/i], category: "frontend" },
129
+ { key: "Vue", patterns: [/vue(\.js|js)/i], category: "frontend" },
130
+ { key: "Angular", patterns: [/angular/i], category: "frontend" },
131
+ { key: "Svelte", patterns: [/svelte/i], category: "frontend" },
132
+ { key: "Next.js", patterns: [/next\.?js/i], category: "frontend" },
133
+ { key: "Nuxt", patterns: [/nuxt/i], category: "frontend" },
134
+ { key: "HTML/CSS/JS", patterns: [/html.*css|vanilla.*js|puro.*js|plain.*js/i], category: "frontend" },
135
+ { key: "Tailwind", patterns: [/tailwind/i], category: "frontend" },
136
+ { key: "Chakra UI", patterns: [/chakra/i], category: "frontend" },
137
+ { key: "Material UI", patterns: [/material[\s-]?ui|mui/i], category: "frontend" },
138
+ { key: "shadcn/ui", patterns: [/shadcn/i], category: "frontend" },
139
+
140
+ // Backend
141
+ { key: "Express", patterns: [/express/i], category: "backend" },
142
+ { key: "Fastify", patterns: [/fastify/i], category: "backend" },
143
+ { key: "NestJS", patterns: [/nestjs/i], category: "backend" },
144
+ { key: "Koa", patterns: [/koa/i], category: "backend" },
145
+ { key: "Hono", patterns: [/hono/i], category: "backend" },
146
+ { key: "Django", patterns: [/django/i], category: "backend" },
147
+ { key: "Flask", patterns: [/flask/i], category: "backend" },
148
+ { key: "FastAPI", patterns: [/fastapi/i], category: "backend" },
149
+ { key: "Rails", patterns: [/rails|ruby on rails/i], category: "backend" },
150
+ { key: "Laravel", patterns: [/laravel/i], category: "backend" },
151
+ { key: "Spring Boot", patterns: [/spring[\s-]?boot/i], category: "backend" },
152
+ { key: "Go stdlib", patterns: [/go\s+stdlib|net\/http/i], category: "backend" },
153
+ { key: "Gin", patterns: [/gin\b/i], category: "backend" },
154
+ { key: "Fiber", patterns: [/fiber/i], category: "backend" },
155
+ { key: "Rust Actix", patterns: [/actix/i], category: "backend" },
156
+ { key: "Rust Axum", patterns: [/axum/i], category: "backend" },
157
+
158
+ // Database
159
+ { key: "PostgreSQL", patterns: [/postgres(ql)?/i], category: "database" },
160
+ { key: "MySQL", patterns: [/mysql/i], category: "database" },
161
+ { key: "SQLite", patterns: [/sqlite/i], category: "database" },
162
+ { key: "MongoDB", patterns: [/mongo(db)?/i], category: "database" },
163
+ { key: "Redis", patterns: [/redis/i], category: "database" },
164
+ { key: "Supabase", patterns: [/supabase/i], category: "database" },
165
+ { key: "Firebase", patterns: [/firebase/i], category: "database" },
166
+ { key: "PlanetScale", patterns: [/planetscale/i], category: "database" },
167
+ { key: "Turso", patterns: [/turso/i], category: "database" },
168
+ { key: "DynamoDB", patterns: [/dynamo(db)?/i], category: "database" },
169
+
170
+ // Auth
171
+ { key: "JWT", patterns: [/jwt/i], category: "auth" },
172
+ { key: "Google OAuth", patterns: [/google\s*oauth|google\s*auth/i], category: "auth" },
173
+ { key: "GitHub OAuth", patterns: [/github\s*oauth|github\s*auth/i], category: "auth" },
174
+ { key: "Session/Cookie", patterns: [/session|cookie/i], category: "auth" },
175
+ { key: "Clerk", patterns: [/clerk/i], category: "auth" },
176
+ { key: "Auth0", patterns: [/auth0/i], category: "auth" },
177
+ { key: "NextAuth", patterns: [/nextauth|next[\s-]?auth/i], category: "auth" },
178
+ { key: "Lucia", patterns: [/lucia/i], category: "auth" },
179
+
180
+ // Language
181
+ { key: "TypeScript", patterns: [/typescript|\.ts\b/i], category: "language" },
182
+ { key: "JavaScript", patterns: [/javascript|\.js\b(?!on)/i], category: "language" },
183
+ { key: "Python", patterns: [/python/i], category: "language" },
184
+ { key: "Go", patterns: [/\bgo\b(?!lang)/i], category: "language" },
185
+ { key: "Rust", patterns: [/rust/i], category: "language" },
186
+ { key: "Java", patterns: [/java(?!script)/i], category: "language" },
187
+ { key: "Ruby", patterns: [/ruby/i], category: "language" },
188
+
189
+ // Testing
190
+ { key: "Jest", patterns: [/jest/i], category: "testing" },
191
+ { key: "Vitest", patterns: [/vitest/i], category: "testing" },
192
+ { key: "Bun test", patterns: [/bun\s*test/i], category: "testing" },
193
+ { key: "Cypress", patterns: [/cypress/i], category: "testing" },
194
+ { key: "Playwright", patterns: [/playwright/i], category: "testing" },
195
+ { key: "pytest", patterns: [/pytest/i], category: "testing" },
196
+ { key: "RSpec", patterns: [/rspec/i], category: "testing" },
197
+ ]
198
+
199
+ for (const detection of techDetections) {
200
+ for (const pattern of detection.patterns) {
201
+ if (pattern.test(briefing)) {
202
+ if (detection.category === "other") {
203
+ analysis.tech_stack.other.push(detection.key)
204
+ } else {
205
+ const stack = analysis.tech_stack as unknown as Record<string, string | null>
206
+ const current = stack[detection.category]
207
+ if (!current) {
208
+ stack[detection.category] = detection.key
209
+ } else {
210
+ analysis.tech_stack.other.push(detection.key)
211
+ }
212
+ }
213
+ analysis.known_facts[`tech_${detection.category}`] = detection.key
214
+ break
215
+ }
216
+ }
217
+ }
218
+
219
+ // Detect auth patterns (backward compat)
220
+ if (analysis.tech_stack.auth) {
221
+ analysis.inferred_auth = analysis.tech_stack.auth.toLowerCase()
222
+ } else if (/login|auth|autenticação/i.test(briefing)) {
223
+ analysis.known_facts["auth_mentioned"] = "true"
224
+ }
225
+
226
+ // Detect multi-tenancy
227
+ if (/multi.?tenant/i.test(briefing)) {
228
+ analysis.known_facts["multi_tenant"] = "true"
229
+ }
230
+
231
+ // Detect entities
232
+ if (shouldDetect("entity")) {
233
+ const entityPatterns: Array<{ pattern: RegExp; name: string }> = [
234
+ { pattern: /(?:usuários?|users?)\b/i, name: "User" },
235
+ { pattern: /(?:tarefas?|todos?|tasks?)\b/i, name: "Todo" },
236
+ { pattern: /(?:produtos?|products?)\b/i, name: "Product" },
237
+ { pattern: /(?:pedidos?|orders?)\b/i, name: "Order" },
238
+ { pattern: /(?:clientes?|customers?)\b/i, name: "Customer" },
239
+ { pattern: /(?:categorias?|categories?)\b/i, name: "Category" },
240
+ { pattern: /(?:projetos?|projects?)\b/i, name: "Project" },
241
+ { pattern: /(?:artigos?|posts?|articles?)\b/i, name: "Post" },
242
+ { pattern: /(?:páginas?|pages?)\b/i, name: "Page" },
243
+ { pattern: /(?:comentários?|comments?)\b/i, name: "Comment" },
244
+ { pattern: /(?:roles?|papéis?)\b/i, name: "Role" },
245
+ { pattern: /(?:planos?|plans?)\b/i, name: "Plan" },
246
+ { pattern: /(?:pagamentos?|payments?)\b/i, name: "Payment" },
247
+ { pattern: /(?:notificações?|notifications?)\b/i, name: "Notification" },
248
+ { pattern: /(?:mensagens?|messages?)\b/i, name: "Message" },
249
+ { pattern: /(?:chat|conversas?)\b/i, name: "Chat" },
250
+ { pattern: /(?:arquivos?|files?)\b/i, name: "File" },
251
+ { pattern: /(?:equipes?|teams?)\b/i, name: "Team" },
252
+ { pattern: /(?:organizações?|organizations?)\b/i, name: "Organization" },
253
+ // Custom entities from options
254
+ ...(options?.customEntities?.map(c => ({ pattern: new RegExp(c.pattern, 'i'), name: c.name })) || []),
255
+ ]
256
+
257
+ const excludeEntitySet = new Set(options?.excludeEntities || [])
258
+ for (const { pattern, name } of entityPatterns) {
259
+ if (pattern.test(briefing) && !analysis.inferred_entities.includes(name) && !excludeEntitySet.has(name)) {
260
+ analysis.inferred_entities.push(name)
261
+ }
262
+ }
263
+ }
264
+
265
+ // Detect domain
266
+ if (shouldDetect("domain")) {
267
+ const domainPatterns: [string, RegExp][] = [
268
+ ["ecommerce", /compr|vend|loja|shop|cart|carrinho|order|pedido/i],
269
+ ["cms", /cms|blog|conteúdo|content|pagina|page|post/i],
270
+ ["saas", /saas|subscription|assinatura|billing|fatura/i],
271
+ ["social", /social|feed|post|comentar|comment|follow|segui/i],
272
+ ["crm", /crm|lead|contact|contato|deal|negócio/i],
273
+ ["erp", /erp|estoque|inventory|fatur|invoice/i],
274
+ ["task_management", /tarefa|todo|task|kanban|board/i],
275
+ ["chat", /chat|mensagem|message|conversa|conversation/i],
276
+ ["education", /curso|course|aula|lesson|student|aluno/i],
277
+ ["healthcare", /médic|doctor|patient|paciente|health|saúde/i],
278
+ // Custom domains from options
279
+ ...(options?.customDomains?.map(c => [c.name, new RegExp(c.pattern, 'i')] as [string, RegExp]) || []),
280
+ ]
281
+
282
+ const excludeDomainSet = new Set(options?.excludeDomains || [])
283
+ for (const [domain, pattern] of domainPatterns) {
284
+ if (pattern.test(briefing) && !excludeDomainSet.has(domain)) {
285
+ analysis.domain_detected = domain
286
+ break
287
+ }
288
+ }
289
+ }
290
+
291
+ // Detect ambiguities
292
+ const ambiguousPatterns = [
293
+ { pattern: /compartilh[ando]+/i, desc: "Mecanismo de compartilhamento não especificado (link público, usuário, organização?)" },
294
+ { pattern: /simples|básico|basic/i, desc: "Nível de complexidade ambíguo - quais funcionalidades estão incluídas/excluídas?" },
295
+ { pattern: /etc|e assim por diante/i, desc: "Enumeração aberta detectada" },
296
+ { pattern: /maybe|talvez|perhaps|pode ser/i, desc: "Funcionalidade mencionada com incerteza" },
297
+ ]
298
+
299
+ for (const { pattern, desc } of ambiguousPatterns) {
300
+ if (pattern.test(briefing)) {
301
+ analysis.ambiguities.push(desc)
302
+ }
303
+ }
304
+
305
+ // Now determine what's MISSING (not already in the briefing)
306
+ buildMissingInformation(analysis)
307
+
308
+ // Store in cache if provided
309
+ if (options?.analysisCache && options.briefingHash) {
310
+ options.analysisCache.set(options.briefingHash, { result: analysis, timestamp: Date.now() })
311
+ }
312
+
313
+ return analysis
314
+ }
315
+
316
+ function extractContextAround(text: string, index: number): string {
317
+ const start = Math.max(0, index - 50)
318
+ const end = Math.min(text.length, index + 50)
319
+ return text.slice(start, end).trim()
320
+ }
321
+
322
+ function buildMissingInformation(analysis: BriefingAnalysis): void {
323
+ const missing = analysis.missing_information
324
+
325
+ // Only add questions for things NOT detected in the briefing
326
+
327
+ // Auth - only if not detected
328
+ if (!analysis.tech_stack.auth && !analysis.known_facts["auth_mentioned"]) {
329
+ missing.push({
330
+ category: "auth",
331
+ description: "Mecanismo de autenticação",
332
+ classification: "CRITICAL",
333
+ already_answered: false,
334
+ question_for_user: {
335
+ question: "Como os usuários farão login no sistema?",
336
+ header: "Autenticação",
337
+ options: [
338
+ { label: "Email + Senha", description: "Cadastro e login com email e senha" },
339
+ { label: "Google OAuth", description: "Login com conta Google" },
340
+ { label: "GitHub OAuth", description: "Login com conta GitHub" },
341
+ { label: "JWT", description: "Autenticação via JSON Web Tokens" },
342
+ { label: "Sessão/ Cookie", description: "Sessão server-side com cookies HTTP-only" },
343
+ { label: "Clerk", description: "Serviço de autenticação Clerk" },
344
+ { label: "Auth0", description: "Serviço de autenticação Auth0" },
345
+ { label: "Sem autenticação", description: "Sistema público, sem login" },
346
+ ],
347
+ },
348
+ })
349
+ }
350
+
351
+ // Frontend - only if not detected
352
+ if (!analysis.tech_stack.frontend) {
353
+ missing.push({
354
+ category: "frontend",
355
+ description: "Framework/frontend",
356
+ classification: "CRITICAL",
357
+ already_answered: false,
358
+ question_for_user: {
359
+ question: "Qual tecnologia será usada no frontend?",
360
+ header: "Frontend",
361
+ options: [
362
+ { label: "React", description: "Biblioteca JavaScript mais popular" },
363
+ { label: "Vue.js", description: "Framework progressivo e flexível" },
364
+ { label: "Angular", description: "Framework completo da Google" },
365
+ { label: "Svelte", description: "Framework reativo compilado" },
366
+ { label: "Next.js", description: "Framework React full-stack" },
367
+ { label: "Nuxt", description: "Framework Vue full-stack" },
368
+ { label: "HTML/CSS/JS puro", description: "Sem framework, código vanilla" },
369
+ { label: "Não aplicável", description: "Backend apenas, sem frontend" },
370
+ ],
371
+ },
372
+ })
373
+ }
374
+
375
+ // Backend - only if not detected
376
+ if (!analysis.tech_stack.backend) {
377
+ missing.push({
378
+ category: "backend",
379
+ description: "Framework/backend",
380
+ classification: "CRITICAL",
381
+ already_answered: false,
382
+ question_for_user: {
383
+ question: "Qual tecnologia será usada no backend?",
384
+ header: "Backend",
385
+ options: [
386
+ { label: "Express", description: "Framework web minimalista para Node.js" },
387
+ { label: "Fastify", description: "Framework web rápido para Node.js" },
388
+ { label: "NestJS", description: "Framework Node.js com arquitetura modular" },
389
+ { label: "Hono", description: "Framework web leve e rápido" },
390
+ { label: "Django", description: "Framework Python full-featured" },
391
+ { label: "FastAPI", description: "Framework Python rápido e assíncrono" },
392
+ { label: "Flask", description: "Micro-framework Python" },
393
+ { label: "Rails", description: "Framework Ruby full-stack" },
394
+ { label: "Laravel", description: "Framework PHP elegante" },
395
+ { label: "Spring Boot", description: "Framework Java corporativo" },
396
+ { label: "Go stdlib", description: "Go padrão com net/http" },
397
+ { label: "Gin", description: "Framework web rápido para Go" },
398
+ { label: "Actix/Axum", description: "Frameworks web para Rust" },
399
+ ],
400
+ },
401
+ })
402
+ }
403
+
404
+ // Database - only if not detected
405
+ if (!analysis.tech_stack.database) {
406
+ missing.push({
407
+ category: "database",
408
+ description: "Banco de dados",
409
+ classification: "CRITICAL",
410
+ already_answered: false,
411
+ question_for_user: {
412
+ question: "Qual banco de dados será utilizado?",
413
+ header: "Banco de Dados",
414
+ options: [
415
+ { label: "SQLite", description: "Banco local, sem servidor, ideal para projetos pequenos" },
416
+ { label: "PostgreSQL", description: "Banco relacional robusto e escalável" },
417
+ { label: "MySQL", description: "Banco relacional popular e maduro" },
418
+ { label: "MongoDB", description: "Banco NoSQL baseado em documentos" },
419
+ { label: "Supabase", description: "BaaS com PostgreSQL + APIs automáticas" },
420
+ { label: "Firebase", description: "BaaS da Google com Firestore/Realtime DB" },
421
+ { label: "Redis", description: "Banco key-value para cache e sessões" },
422
+ { label: "Turso", description: "SQLite distribuído na borda" },
423
+ { label: "DynamoDB", description: "Banco NoSQL da AWS" },
424
+ { label: "Sem banco", description: "Sistema sem persistência" },
425
+ ],
426
+ },
427
+ })
428
+ }
429
+
430
+ // Delete behavior - always ask (it's a business decision)
431
+ missing.push({
432
+ category: "delete_behavior",
433
+ description: "Comportamento de exclusão",
434
+ classification: "IMPORTANT",
435
+ already_answered: false,
436
+ question_for_user: {
437
+ question: "Como devem funcionar as exclusões no sistema?",
438
+ header: "Exclusão",
439
+ options: [
440
+ { label: "Hard delete", description: "Registros são removidos permanentemente" },
441
+ { label: "Soft delete", description: "Registros são marcados como deletados mas mantidos" },
442
+ ],
443
+ },
444
+ })
445
+
446
+ // Business rules - only if not enough context
447
+ if (analysis.inferred_entities.length > 0) {
448
+ missing.push({
449
+ category: "business_rules",
450
+ description: "Regras de negócio específicas",
451
+ classification: "OPTIONAL",
452
+ already_answered: false,
453
+ question_for_user: {
454
+ question: "Existem regras de negócio específicas para as entidades detectadas?",
455
+ header: "Regras de Negócio",
456
+ options: [
457
+ { label: "Não por agora", description: "Prosseguir com regras padrão" },
458
+ { label: "Sim, vou especificar", description: "Quero definir regras específicas" },
459
+ ],
460
+ },
461
+ })
462
+ }
463
+
464
+ // Multi-tenancy - if not detected
465
+ if (!analysis.tech_stack.frontend && !analysis.known_facts["multi_tenant"]) {
466
+ const text = Object.values(analysis.known_facts).join(" ").toLowerCase()
467
+ if (/tenant|multi.?tenant|organiza/i.test(text)) {
468
+ missing.push({
469
+ category: "multi_tenancy",
470
+ description: "Estratégia de multi-tenancy",
471
+ classification: "IMPORTANT",
472
+ already_answered: false,
473
+ question_for_user: {
474
+ question: "O sistema precisa de multi-tenancy?",
475
+ header: "Multi-Tenancy",
476
+ options: [
477
+ { label: "Não", description: "Sistema single-tenant" },
478
+ { label: "Sim, por schema", description: "Isolamento por schema no banco" },
479
+ { label: "Sim, por coluna", description: "Isolamento por tenant_id em cada tabela" },
480
+ { label: "Sim, por banco", description: "Um banco de dados por tenant" },
481
+ ],
482
+ },
483
+ })
484
+ }
485
+ }
486
+
487
+ // Deployment - always ask
488
+ missing.push({
489
+ category: "deployment",
490
+ description: "Estratégia de deploy",
491
+ classification: "IMPORTANT",
492
+ already_answered: false,
493
+ question_for_user: {
494
+ question: "Como o sistema será deployado?",
495
+ header: "Deploy",
496
+ options: [
497
+ { label: "Docker", description: "Containerização com Docker" },
498
+ { label: "Vercel/Netlify", description: "Deploy serverless" },
499
+ { label: "VPS tradicional", description: "Servidor dedicado ou VPS" },
500
+ { label: "Kubernetes", description: "Orquestração com K8s" },
501
+ { label: "AWS/GCP/Azure", description: "Cloud provider" },
502
+ { label: "Ainda não definido", description: "Decidir depois" },
503
+ ],
504
+ },
505
+ })
506
+
507
+ // API versioning - if API detected
508
+ if (analysis.inferred_entities.length > 0) {
509
+ missing.push({
510
+ category: "api_versioning",
511
+ description: "Versionamento da API",
512
+ classification: "OPTIONAL",
513
+ already_answered: false,
514
+ question_for_user: {
515
+ question: "Como a API será versionada?",
516
+ header: "API Versioning",
517
+ options: [
518
+ { label: "URL path (/v1/)", description: "Versão no path da URL" },
519
+ { label: "Header", description: "Versão no header Accept" },
520
+ { label: "Query param", description: "Versão como query parameter" },
521
+ { label: "Sem versionamento", description: "API sem controle de versão" },
522
+ ],
523
+ },
524
+ })
525
+ }
526
+
527
+ // Testing strategy
528
+ if (!analysis.tech_stack.testing) {
529
+ missing.push({
530
+ category: "testing",
531
+ description: "Estratégia de testes",
532
+ classification: "OPTIONAL",
533
+ already_answered: false,
534
+ question_for_user: {
535
+ question: "Qual estratégia de testes será usada?",
536
+ header: "Testes",
537
+ options: [
538
+ { label: "Unit tests", description: "Testes unitários com Jest/Vitest" },
539
+ { label: "Integration tests", description: "Testes de integração + E2E" },
540
+ { label: "TDD", description: "Desenvolvimento orientado a testes" },
541
+ { label: "Sem testes por agora", description: "Adicionar testes depois" },
542
+ ],
543
+ },
544
+ })
545
+ }
546
+ }
547
+
548
+ /**
549
+ * Options for controlling question generation scope.
550
+ */
551
+ export interface QuestionGenerationOptions {
552
+ /** Skip these categories (e.g., ["auth", "frontend"]). */
553
+ excludeCategories?: string[]
554
+ /** Only generate questions for these categories. */
555
+ focusCategories?: string[]
556
+ /** Questions already asked by the IA — skip these. */
557
+ alreadyAsked?: string[]
558
+ /** Maximum questions to generate. */
559
+ maxQuestions?: number
560
+ /** Only generate questions at these classifications. */
561
+ focusClassifications?: Array<"CRITICAL" | "IMPORTANT" | "OPTIONAL" | "UNKNOWN">
562
+ }
563
+
564
+ export function generateDiscoveryQuestions(
565
+ analysis: BriefingAnalysis,
566
+ options?: QuestionGenerationOptions,
567
+ ): QuestionForUser[] {
568
+ const excludeSet = new Set(options?.excludeCategories || [])
569
+ const focusSet = options?.focusCategories?.length ? new Set(options.focusCategories) : null
570
+ const askedSet = new Set(options?.alreadyAsked?.map(q => q.toLowerCase()) || [])
571
+ const focusClassSet = options?.focusClassifications?.length ? new Set(options.focusClassifications) : null
572
+
573
+ const questions = analysis.missing_information
574
+ .filter((m) => {
575
+ if (m.already_answered) return false
576
+ if (!m.question_for_user) return false
577
+ if (excludeSet.has(m.category)) return false
578
+ if (focusSet && !focusSet.has(m.category)) return false
579
+ if (focusClassSet && !focusClassSet.has(m.classification)) return false
580
+ // Skip if already asked
581
+ const qLower = m.question_for_user.question.toLowerCase()
582
+ if (askedSet.has(qLower)) return false
583
+ return true
584
+ })
585
+ .map((m) => m.question_for_user!)
586
+
587
+ if (options?.maxQuestions && questions.length > options.maxQuestions) {
588
+ return questions.slice(0, options.maxQuestions)
589
+ }
590
+
591
+ return questions
592
+ }
593
+
594
+ export function updateGraphFromAnswers(
595
+ graph: KnowledgeGraph,
596
+ answers: Record<string, string>,
597
+ ): void {
598
+ const now = new Date().toISOString()
599
+
600
+ for (const [question, answer] of Object.entries(answers)) {
601
+ const lowerQ = question.toLowerCase()
602
+
603
+ // Auth type
604
+ if (lowerQ.includes("login") || lowerQ.includes("autenticação")) {
605
+ let authType = answer
606
+ addNode(graph, {
607
+ id: `${graph.project_id}-AUTH`,
608
+ type: "architecture_component",
609
+ name: "Authentication",
610
+ description: `Authentication mechanism: ${authType}`,
611
+ status: "APPROVED",
612
+ version: 1,
613
+ metadata: { layer: "backend", technology: authType },
614
+ created_at: now,
615
+ updated_at: now,
616
+ })
617
+ }
618
+
619
+ // Frontend
620
+ if (lowerQ.includes("frontend")) {
621
+ addNode(graph, {
622
+ id: `${graph.project_id}-FE`,
623
+ type: "architecture_component",
624
+ name: "Frontend",
625
+ description: `Frontend: ${answer}`,
626
+ status: "APPROVED",
627
+ version: 1,
628
+ metadata: { layer: "frontend", technology: answer },
629
+ created_at: now,
630
+ updated_at: now,
631
+ })
632
+ }
633
+
634
+ // Backend
635
+ if (lowerQ.includes("backend")) {
636
+ addNode(graph, {
637
+ id: `${graph.project_id}-BE`,
638
+ type: "architecture_component",
639
+ name: "Backend",
640
+ description: `Backend: ${answer}`,
641
+ status: "APPROVED",
642
+ version: 1,
643
+ metadata: { layer: "backend", technology: answer },
644
+ created_at: now,
645
+ updated_at: now,
646
+ })
647
+ }
648
+
649
+ // Database
650
+ if (lowerQ.includes("banco") || lowerQ.includes("database")) {
651
+ addNode(graph, {
652
+ id: `${graph.project_id}-DB`,
653
+ type: "database",
654
+ name: "Database",
655
+ description: `Database: ${answer}`,
656
+ status: "APPROVED",
657
+ version: 1,
658
+ metadata: { engine: answer.toLowerCase() },
659
+ created_at: now,
660
+ updated_at: now,
661
+ })
662
+ }
663
+
664
+ // Multi-tenancy
665
+ if (lowerQ.includes("tenant")) {
666
+ const isMultiTenant = /sim|yes|true/i.test(answer) || /multi/i.test(answer)
667
+ if (isMultiTenant) {
668
+ addNode(graph, {
669
+ id: `${graph.project_id}-TENANT`,
670
+ type: "entity",
671
+ name: "Tenant",
672
+ description: "Tenant entity for multi-tenancy",
673
+ status: "APPROVED",
674
+ version: 1,
675
+ metadata: {
676
+ fields: [
677
+ { name: "id", type: "uuid", primary_key: true },
678
+ { name: "name", type: "string", required: true },
679
+ { name: "created_at", type: "timestamp" },
680
+ ] as Array<{ name: string; type: string; primary_key?: boolean; required?: boolean }>,
681
+ },
682
+ created_at: now,
683
+ updated_at: now,
684
+ })
685
+ }
686
+ }
687
+
688
+ // Delete behavior
689
+ if (lowerQ.includes("exclusão") || lowerQ.includes("delete")) {
690
+ const isSoftDelete = /soft|reversível|reversivel/i.test(answer)
691
+ addNode(graph, {
692
+ id: `${graph.project_id}-RULE-DELETE`,
693
+ type: "business_rule",
694
+ name: "Delete Behavior",
695
+ description: isSoftDelete
696
+ ? "Entities use soft delete (marked as deleted, not removed)"
697
+ : "Entities use hard delete (permanently removed)",
698
+ status: "APPROVED",
699
+ version: 1,
700
+ metadata: {
701
+ rule_text: isSoftDelete
702
+ ? "Soft delete: records are marked with deleted_at timestamp"
703
+ : "Hard delete: records are permanently removed from database",
704
+ },
705
+ created_at: now,
706
+ updated_at: now,
707
+ })
708
+ }
709
+ }
710
+ }
711
+
712
+ export function isBriefingSufficient(analysis: BriefingAnalysis): boolean {
713
+ const criticalMissing = analysis.missing_information.filter(
714
+ (m) => m.classification === "CRITICAL" && !m.already_answered,
715
+ )
716
+ return criticalMissing.length === 0
717
+ }
718
+
719
+ export function formatDiscoverySummary(analysis: BriefingAnalysis): string {
720
+ const lines: string[] = ["## Briefing Analysis\n"]
721
+
722
+ // Tech stack detected
723
+ const techs = Object.entries(analysis.tech_stack).filter(([, v]) => v !== null && v !== "")
724
+ if (techs.length > 0) {
725
+ lines.push("### Tech Stack Detectado")
726
+ for (const [key, value] of techs) {
727
+ if (key === "other") continue
728
+ lines.push(`- **${key}:** ${value}`)
729
+ }
730
+ lines.push("")
731
+ }
732
+
733
+ if (Object.keys(analysis.known_facts).length > 0) {
734
+ lines.push("### Informações Detectadas")
735
+ for (const [key, value] of Object.entries(analysis.known_facts)) {
736
+ if (key.startsWith("tech_")) continue
737
+ lines.push(`- ${key}: ${value}`)
738
+ }
739
+ lines.push("")
740
+ }
741
+
742
+ if (analysis.inferred_entities.length > 0) {
743
+ lines.push("### Entidades Detectadas")
744
+ lines.push(`- ${analysis.inferred_entities.join(", ")}`)
745
+ lines.push("")
746
+ }
747
+
748
+ if (analysis.file_references.length > 0) {
749
+ lines.push("### Arquivos Referenciados (@)")
750
+ for (const ref of analysis.file_references) {
751
+ lines.push(`- \`${ref.path}\` — contexto: ${ref.context}`)
752
+ }
753
+ lines.push("")
754
+ }
755
+
756
+ if (analysis.domain_detected) {
757
+ lines.push(`### Domínio Detectado: ${analysis.domain_detected}`)
758
+ lines.push("")
759
+ }
760
+
761
+ if (analysis.ambiguities.length > 0) {
762
+ lines.push("### Ambiguidades Detectadas")
763
+ for (const a of analysis.ambiguities) {
764
+ lines.push(`- ${a}`)
765
+ }
766
+ lines.push("")
767
+ }
768
+
769
+ return lines.join("\n")
770
+ }