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,1023 @@
1
+ import { getNodesByType } from "../graph/engine.js";
2
+ import { getExclusionSets, isNodeExcludedOrDeprecated } from "../drift/exclusion.js";
3
+ import { writeFileSync, mkdirSync, existsSync } from "fs";
4
+ import { dirname, resolve, relative } from "path";
5
+ export function detectTechStack(graph) {
6
+ const archNodes = getNodesByType(graph, "architecture_component");
7
+ const dbNodes = getNodesByType(graph, "database");
8
+ const stack = {};
9
+ for (const arch of archNodes) {
10
+ const tech = arch.metadata.technology?.toLowerCase() || "";
11
+ const layer = arch.metadata.layer;
12
+ if (layer === "frontend") {
13
+ if (tech.includes("react"))
14
+ stack.frontend = "react";
15
+ else if (tech.includes("vue"))
16
+ stack.frontend = "vue";
17
+ else if (tech.includes("angular"))
18
+ stack.frontend = "angular";
19
+ else if (tech.includes("svelte"))
20
+ stack.frontend = "svelte";
21
+ else
22
+ stack.frontend = tech || undefined;
23
+ }
24
+ if (layer === "backend") {
25
+ if (tech.includes("express"))
26
+ stack.backend = "express";
27
+ else if (tech.includes("fastify"))
28
+ stack.backend = "fastify";
29
+ else if (tech.includes("nestjs"))
30
+ stack.backend = "nestjs";
31
+ else if (tech.includes("django"))
32
+ stack.backend = "django";
33
+ else if (tech.includes("fastapi"))
34
+ stack.backend = "fastapi";
35
+ else if (tech.includes("flask"))
36
+ stack.backend = "flask";
37
+ else if (tech.includes("rails"))
38
+ stack.backend = "rails";
39
+ else if (tech.includes("laravel"))
40
+ stack.backend = "laravel";
41
+ else if (tech.includes("gin"))
42
+ stack.backend = "gin";
43
+ else if (tech.includes("fiber"))
44
+ stack.backend = "fiber";
45
+ else if (tech.includes("actix") || tech.includes("axum"))
46
+ stack.backend = "rust";
47
+ else if (tech.includes("spring"))
48
+ stack.backend = "spring";
49
+ else
50
+ stack.backend = tech || undefined;
51
+ }
52
+ }
53
+ for (const db of dbNodes) {
54
+ const engine = db.metadata.engine?.toLowerCase() || "";
55
+ if (engine.includes("postgres"))
56
+ stack.database = "postgresql";
57
+ else if (engine.includes("mysql"))
58
+ stack.database = "mysql";
59
+ else if (engine.includes("sqlite"))
60
+ stack.database = "sqlite";
61
+ else if (engine.includes("mongo"))
62
+ stack.database = "mongodb";
63
+ else if (engine.includes("redis"))
64
+ stack.database = "redis";
65
+ else
66
+ stack.database = engine || undefined;
67
+ }
68
+ return stack;
69
+ }
70
+ const SUPPORTED_BACKENDS = new Set(["express", "fastify", "nestjs"]);
71
+ const SUPPORTED_FRONTENDS = new Set(["react"]);
72
+ const SUPPORTED_DATABASES = new Set(["sqlite", "postgresql", "mysql"]);
73
+ export function hasCodegenSupport(stack) {
74
+ return (!stack.backend || SUPPORTED_BACKENDS.has(stack.backend)) && (!stack.frontend || SUPPORTED_FRONTENDS.has(stack.frontend)) && (!stack.database || SUPPORTED_DATABASES.has(stack.database));
75
+ }
76
+ export function generateProject(graph, stack) {
77
+ const detectedStack = stack || detectTechStack(graph);
78
+ // If the stack is partially/fully unknown, return a spec prompt for the AI to generate
79
+ if (!hasCodegenSupport(detectedStack)) {
80
+ return generateSpecPrompt(graph, detectedStack);
81
+ }
82
+ const { removed, deprecated } = getExclusionSets(graph);
83
+ const entities = getNodesByType(graph, "entity")
84
+ .filter((e) => !isNodeExcludedOrDeprecated(e.id, e.status, removed, deprecated));
85
+ const features = getNodesByType(graph, "feature")
86
+ .filter((f) => !isNodeExcludedOrDeprecated(f.id, f.status, removed, deprecated));
87
+ const endpoints = getNodesByType(graph, "endpoint")
88
+ .filter((e) => !isNodeExcludedOrDeprecated(e.id, e.status, removed, deprecated));
89
+ const tables = getNodesByType(graph, "table")
90
+ .filter((t) => !isNodeExcludedOrDeprecated(t.id, t.status, removed, deprecated));
91
+ const businessRules = getNodesByType(graph, "business_rule")
92
+ .filter((b) => !isNodeExcludedOrDeprecated(b.id, b.status, removed, deprecated));
93
+ const files = [];
94
+ const directories = new Set();
95
+ // Generate backend
96
+ if (detectedStack.backend === "express" || detectedStack.backend === "fastify") {
97
+ generateExpressBackend(graph, entities, endpoints, tables, businessRules, files, directories, detectedStack);
98
+ }
99
+ // Generate frontend
100
+ if (detectedStack.frontend === "react") {
101
+ generateReactFrontend(graph, entities, features, endpoints, files, directories, detectedStack);
102
+ }
103
+ // Generate database schema
104
+ generateDatabaseSchema(graph, entities, tables, files, directories, detectedStack);
105
+ // Generate tests
106
+ generateTests(graph, entities, endpoints, files, directories, detectedStack);
107
+ // Generate shared types
108
+ generateSharedTypes(graph, entities, files, directories, detectedStack);
109
+ const dirList = [...directories].sort();
110
+ return {
111
+ files,
112
+ directories: dirList,
113
+ summary: buildGenerationSummary(graph, entities, features, files, detectedStack),
114
+ };
115
+ }
116
+ function generateSpecPrompt(graph, stack) {
117
+ const entities = getNodesByType(graph, "entity");
118
+ const endpoints = getNodesByType(graph, "endpoint");
119
+ const businessRules = getNodesByType(graph, "business_rule");
120
+ // ── Context-aware: gather decisions, constraints, architecture ──
121
+ const decisions = graph.nodes.filter(n => n.type === "decision");
122
+ const constraints = graph.nodes.filter(n => n.type === "constraint");
123
+ const archComponents = graph.nodes.filter(n => n.type === "architecture_component");
124
+ const constitution = graph.nodes.find(n => n.type === "constitution");
125
+ const stackDesc = [
126
+ stack.frontend && `Frontend: ${stack.frontend}`,
127
+ stack.backend && `Backend: ${stack.backend}`,
128
+ stack.database && `Database: ${stack.database}`,
129
+ stack.language && `Language: ${stack.language}`,
130
+ ].filter(Boolean).join(" | ") || "Unknown stack";
131
+ const entityList = entities.map((e) => {
132
+ const fields = (e.metadata.fields || []).map((f) => ` - ${f.name}: ${f.type}${f.required ? " (required)" : ""}`).join("\n");
133
+ return `- **${e.name}**\n${fields}`;
134
+ }).join("\n");
135
+ const endpointList = endpoints.map((ep) => {
136
+ const meta = ep.metadata;
137
+ return `- \`${meta.method || "GET"} ${meta.path || ep.name}\` — ${ep.description || ep.name}`;
138
+ }).join("\n");
139
+ const rulesList = businessRules.map((r) => `- **${r.name}:** ${r.description || r.metadata.rule_text || ""}`).join("\n");
140
+ // Context sections
141
+ const decisionsList = decisions.map((d) => {
142
+ const meta = d.metadata;
143
+ return `- **${meta.title || d.name}:** ${meta.decision || d.description}`;
144
+ }).join("\n");
145
+ const constraintsList = constraints.map((c) => {
146
+ const meta = c.metadata;
147
+ return `- [${meta.constraint_type || "technical"}] ${meta.rule_text || c.description}`;
148
+ }).join("\n");
149
+ const archList = archComponents.map((a) => {
150
+ const meta = a.metadata;
151
+ return `- **${a.name}** (${meta.layer}): ${meta.technology || "unknown"} — ${a.description || ""}`;
152
+ }).join("\n");
153
+ const principlesList = (() => {
154
+ if (!constitution)
155
+ return "";
156
+ const meta = constitution.metadata;
157
+ if (!meta.principles)
158
+ return "";
159
+ return meta.principles.map((p) => `- [${p.severity}] ${p.rule}`).join("\n");
160
+ })();
161
+ const prompt = [
162
+ `## Code Generation Prompt`,
163
+ ``,
164
+ `**Detected Stack:** ${stackDesc}`,
165
+ `**Note:** The detected tech stack is not in the set of stacks with built-in templates.`,
166
+ `Generate the project code using your knowledge of the specified technologies.`,
167
+ ``,
168
+ `### Entities`,
169
+ entityList || "No entities defined.",
170
+ ``,
171
+ `### API Endpoints`,
172
+ endpointList || "No endpoints defined.",
173
+ ``,
174
+ `### Business Rules`,
175
+ rulesList || "No business rules defined.",
176
+ ``,
177
+ ];
178
+ if (decisionsList) {
179
+ prompt.push(`### Architecture Decisions (ADRs)`, decisionsList, ``);
180
+ }
181
+ if (constraintsList) {
182
+ prompt.push(`### Constraints`, constraintsList, ``);
183
+ }
184
+ if (archList) {
185
+ prompt.push(`### Architecture Components`, archList, ``);
186
+ }
187
+ if (principlesList) {
188
+ prompt.push(`### Constitution (Mandatory Principles)`, principlesList, ``);
189
+ }
190
+ prompt.push(`### Instructions`, `Generate a complete project structure for a ${stackDesc} application.`, `Include:`, `1. Project configuration files (package.json, tsconfig, etc.)`, `2. Backend: routes, controllers/services, database access layer`, `3. Frontend: components, pages, state management`, `4. Database schema/migrations`, `5. Tests`, `6. README with setup instructions`, ``, `Follow the conventions and patterns commonly used with the specified technologies.`, `Use the entity fields and API endpoints above to generate the actual code.`);
191
+ if (decisionsList) {
192
+ prompt.push(`Respect the architecture decisions listed above.`);
193
+ }
194
+ if (constraintsList) {
195
+ prompt.push(`Apply all constraints listed above.`);
196
+ }
197
+ if (principlesList) {
198
+ prompt.push(`Follow ALL constitution principles — they are mandatory.`);
199
+ }
200
+ return {
201
+ files: [],
202
+ directories: [],
203
+ summary: prompt.join("\n"),
204
+ };
205
+ }
206
+ function generateExpressBackend(_graph, entities, _endpoints, _tables, _rules, files, dirs, _stack) {
207
+ dirs.add("src/server");
208
+ dirs.add("src/server/routes");
209
+ dirs.add("src/server/controllers");
210
+ dirs.add("src/server/services");
211
+ dirs.add("src/server/repositories");
212
+ dirs.add("src/server/middleware");
213
+ dirs.add("src/server/models");
214
+ // Server entry
215
+ files.push({
216
+ path: "src/server/index.ts",
217
+ description: "Express server entry point",
218
+ content: `import express from "express"
219
+ import cors from "cors"
220
+ import { router } from "./routes/index.js"
221
+
222
+ const app = express()
223
+ const PORT = process.env.PORT || 3000
224
+
225
+ app.use(cors())
226
+ app.use(express.json())
227
+
228
+ app.use("/api", router)
229
+
230
+ app.listen(PORT, () => {
231
+ console.log(\`Server running on port \${PORT}\`)
232
+ })
233
+ `,
234
+ });
235
+ // Routes index
236
+ const routeImports = entities.map((e) => {
237
+ const name = e.name.toLowerCase();
238
+ return `import { ${name}Router } from "./${name}.js"`;
239
+ }).join("\n");
240
+ const routeUses = entities.map((e) => {
241
+ const name = e.name.toLowerCase();
242
+ return `router.use("/${name}s", ${name}Router)`;
243
+ }).join("\n");
244
+ files.push({
245
+ path: "src/server/routes/index.ts",
246
+ description: "Route aggregator",
247
+ content: `import { Router } from "express"
248
+ ${routeImports}
249
+
250
+ const router = Router()
251
+ ${routeUses}
252
+
253
+ export { router }
254
+ `,
255
+ });
256
+ // Generate per-entity: model, repository, service, controller, routes
257
+ for (const entity of entities) {
258
+ const name = entity.name;
259
+ const nameLower = name.toLowerCase();
260
+ const namePlural = `${nameLower}s`;
261
+ const fields = entity.metadata.fields || [];
262
+ // Model
263
+ const modelFields = fields.map((f) => {
264
+ const tsType = mapToTsType(f.type);
265
+ const optional = f.required ? "" : "?";
266
+ return ` ${f.name}${optional}: ${tsType}`;
267
+ }).join("\n");
268
+ files.push({
269
+ path: `src/server/models/${nameLower}.ts`,
270
+ description: `${name} model/type definition`,
271
+ content: `export interface ${name} {
272
+ id: string
273
+ ${modelFields}
274
+ created_at: Date
275
+ updated_at: Date
276
+ }
277
+
278
+ export type Create${name}Input = Omit<${name}, "id" | "created_at" | "updated_at">
279
+ export type Update${name}Input = Partial<Create${name}Input>
280
+ `,
281
+ });
282
+ // Repository
283
+ files.push({
284
+ path: `src/server/repositories/${nameLower}.repository.ts`,
285
+ description: `${name} repository (database access)`,
286
+ content: `import { db } from "../database.js"
287
+ import type { ${name}, Create${name}Input, Update${name}Input } from "../models/${nameLower}.js"
288
+
289
+ export const ${name}Repository = {
290
+ async findAll(): Promise<${name}[]> {
291
+ return db.select().from("${namePlural}")
292
+ },
293
+
294
+ async findById(id: string): Promise<${name} | undefined> {
295
+ return db.select().from("${namePlural}").where({ id }).first()
296
+ },
297
+
298
+ async create(data: Create${name}Input): Promise<${name}> {
299
+ const id = crypto.randomUUID()
300
+ const now = new Date()
301
+ await db.insert("${namePlural}").values({ id, ...data, created_at: now, updated_at: now })
302
+ return { id, ...data, created_at: now, updated_at: now }
303
+ },
304
+
305
+ async update(id: string, data: Update${name}Input): Promise<${name} | undefined> {
306
+ const existing = await this.findById(id)
307
+ if (!existing) return undefined
308
+ const updated = { ...existing, ...data, updated_at: new Date() }
309
+ await db.update("${namePlural}").set(updated).where({ id })
310
+ return updated
311
+ },
312
+
313
+ async delete(id: string): Promise<boolean> {
314
+ const result = await db.delete("${namePlural}").where({ id })
315
+ return result.changes > 0
316
+ },
317
+ }
318
+ `,
319
+ });
320
+ // Service
321
+ files.push({
322
+ path: `src/server/services/${nameLower}.service.ts`,
323
+ description: `${name} service (business logic)`,
324
+ content: `import { ${name}Repository } from "../repositories/${nameLower}.repository.js"
325
+ import type { Create${name}Input, Update${name}Input } from "../models/${nameLower}.js"
326
+
327
+ export const ${name}Service = {
328
+ async list() {
329
+ return ${name}Repository.findAll()
330
+ },
331
+
332
+ async getById(id: string) {
333
+ const item = await ${name}Repository.findById(id)
334
+ if (!item) throw new Error("${name} not found")
335
+ return item
336
+ },
337
+
338
+ async create(data: Create${name}Input) {
339
+ return ${name}Repository.create(data)
340
+ },
341
+
342
+ async update(id: string, data: Update${name}Input) {
343
+ const item = await ${name}Repository.update(id, data)
344
+ if (!item) throw new Error("${name} not found")
345
+ return item
346
+ },
347
+
348
+ async delete(id: string) {
349
+ const deleted = await ${name}Repository.delete(id)
350
+ if (!deleted) throw new Error("${name} not found")
351
+ },
352
+ }
353
+ `,
354
+ });
355
+ // Controller
356
+ files.push({
357
+ path: `src/server/controllers/${nameLower}.controller.ts`,
358
+ description: `${name} controller (HTTP handling)`,
359
+ content: `import type { Request, Response } from "express"
360
+ import { ${name}Service } from "../services/${nameLower}.service.js"
361
+
362
+ export const ${name}Controller = {
363
+ async list(_req: Request, res: Response) {
364
+ try {
365
+ const items = await ${name}Service.list()
366
+ res.json(items)
367
+ } catch (err) {
368
+ res.status(500).json({ error: (err as Error).message })
369
+ }
370
+ },
371
+
372
+ async getById(req: Request, res: Response) {
373
+ try {
374
+ const item = await ${name}Service.getById(req.params.id)
375
+ res.json(item)
376
+ } catch (err) {
377
+ res.status(404).json({ error: (err as Error).message })
378
+ }
379
+ },
380
+
381
+ async create(req: Request, res: Response) {
382
+ try {
383
+ const item = await ${name}Service.create(req.body)
384
+ res.status(201).json(item)
385
+ } catch (err) {
386
+ res.status(400).json({ error: (err as Error).message })
387
+ }
388
+ },
389
+
390
+ async update(req: Request, res: Response) {
391
+ try {
392
+ const item = await ${name}Service.update(req.params.id, req.body)
393
+ res.json(item)
394
+ } catch (err) {
395
+ res.status(400).json({ error: (err as Error).message })
396
+ }
397
+ },
398
+
399
+ async remove(req: Request, res: Response) {
400
+ try {
401
+ await ${name}Service.delete(req.params.id)
402
+ res.status(204).end()
403
+ } catch (err) {
404
+ res.status(404).json({ error: (err as Error).message })
405
+ }
406
+ },
407
+ }
408
+ `,
409
+ });
410
+ // Routes
411
+ files.push({
412
+ path: `src/server/routes/${nameLower}.ts`,
413
+ description: `${name} routes`,
414
+ content: `import { Router } from "express"
415
+ import { ${name}Controller } from "../controllers/${nameLower}.controller.js"
416
+
417
+ export const ${nameLower}Router = Router()
418
+
419
+ ${nameLower}Router.get("/", ${name}Controller.list)
420
+ ${nameLower}Router.get("/:id", ${name}Controller.getById)
421
+ ${nameLower}Router.post("/", ${name}Controller.create)
422
+ ${nameLower}Router.put("/:id", ${name}Controller.update)
423
+ ${nameLower}Router.delete("/:id", ${name}Controller.remove)
424
+ `,
425
+ });
426
+ }
427
+ }
428
+ function generateReactFrontend(graph, entities, _features, _endpoints, files, dirs, _stack) {
429
+ dirs.add("src/client");
430
+ dirs.add("src/client/components");
431
+ dirs.add("src/client/pages");
432
+ dirs.add("src/client/hooks");
433
+ dirs.add("src/client/services");
434
+ // API client
435
+ files.push({
436
+ path: "src/client/services/api.ts",
437
+ description: "API client",
438
+ content: `const API_BASE = import.meta.env.VITE_API_URL || "http://localhost:3000/api"
439
+
440
+ async function request<T>(path: string, options?: RequestInit): Promise<T> {
441
+ const res = await fetch(\`\${API_BASE}\${path}\`, {
442
+ headers: { "Content-Type": "application/json" },
443
+ ...options,
444
+ })
445
+ if (!res.ok) throw new Error(await res.text())
446
+ if (res.status === 204) return undefined as T
447
+ return res.json()
448
+ }
449
+
450
+ export const api = {
451
+ get: <T>(path: string) => request<T>(path),
452
+ post: <T>(path: string, data: unknown) => request<T>(path, { method: "POST", body: JSON.stringify(data) }),
453
+ put: <T>(path: string, data: unknown) => request<T>(path, { method: "PUT", body: JSON.stringify(data) }),
454
+ delete: <T>(path: string) => request<T>(path, { method: "DELETE" }),
455
+ }
456
+ `,
457
+ });
458
+ // Generate per-entity: hook, list component, form component, page
459
+ for (const entity of entities) {
460
+ const name = entity.name;
461
+ const nameLower = name.toLowerCase();
462
+ const namePlural = `${nameLower}s`;
463
+ const fields = entity.metadata.fields || [];
464
+ // Hook
465
+ const hookFields = fields.filter(f => f.name !== "id").map(f => {
466
+ const tsType = mapToTsType(f.type);
467
+ return ` ${f.name}: ${tsType}`;
468
+ }).join("\n");
469
+ files.push({
470
+ path: `src/client/hooks/use${name}.ts`,
471
+ description: `${name} CRUD hook`,
472
+ content: `import { useState, useEffect, useCallback } from "react"
473
+ import { api } from "../services/api.js"
474
+
475
+ export interface ${name} {
476
+ id: string
477
+ ${hookFields}
478
+ created_at: string
479
+ updated_at: string
480
+ }
481
+
482
+ export function use${namePlural.charAt(0).toUpperCase() + namePlural.slice(1)}() {
483
+ const [items, setItems] = useState<${name}[]>([])
484
+ const [loading, setLoading] = useState(true)
485
+ const [error, setError] = useState<string | null>(null)
486
+
487
+ const fetchAll = useCallback(async () => {
488
+ try {
489
+ setLoading(true)
490
+ const data = await api.get<${name}[]>("/${namePlural}")
491
+ setItems(data)
492
+ } catch (err) {
493
+ setError((err as Error).message)
494
+ } finally {
495
+ setLoading(false)
496
+ }
497
+ }, [])
498
+
499
+ useEffect(() => { fetchAll() }, [fetchAll])
500
+
501
+ const create = async (data: Omit<${name}, "id" | "created_at" | "updated_at">) => {
502
+ const item = await api.post<${name}>("/${namePlural}", data)
503
+ setItems(prev => [...prev, item])
504
+ return item
505
+ }
506
+
507
+ const update = async (id: string, data: Partial<Omit<${name}, "id">>) => {
508
+ const item = await api.put<${name}>(\`/${namePlural}/\${id}\`, data)
509
+ setItems(prev => prev.map(i => i.id === id ? item : i))
510
+ return item
511
+ }
512
+
513
+ const remove = async (id: string) => {
514
+ await api.delete(\`/${namePlural}/\${id}\`)
515
+ setItems(prev => prev.filter(i => i.id !== id))
516
+ }
517
+
518
+ return { items, loading, error, create, update, remove, refetch: fetchAll }
519
+ }
520
+ `,
521
+ });
522
+ // List component
523
+ const tableHeaders = fields.slice(0, 5).map(f => ` <th className="px-4 py-2 text-left text-sm font-medium text-gray-700">${f.name}</th>`).join("\n");
524
+ const tableCells = fields.slice(0, 5).map(f => ` <td className="px-4 py-2 text-sm text-gray-600">{item.${f.name}}</td>`).join("\n");
525
+ files.push({
526
+ path: `src/client/components/${name}List.tsx`,
527
+ description: `${name} list/table component`,
528
+ content: `import type { ${name} } from "../hooks/use${name}.js"
529
+
530
+ interface ${name}ListProps {
531
+ items: ${name}[]
532
+ onEdit: (item: ${name}) => void
533
+ onDelete: (id: string) => void
534
+ }
535
+
536
+ export function ${name}List({ items, onEdit, onDelete }: ${name}ListProps) {
537
+ return (
538
+ <div className="overflow-x-auto">
539
+ <table className="min-w-full divide-y divide-gray-200">
540
+ <thead className="bg-gray-50">
541
+ <tr>
542
+ ${tableHeaders}
543
+ <th className="px-4 py-2 text-right text-sm font-medium">Actions</th>
544
+ </tr>
545
+ </thead>
546
+ <tbody className="bg-white divide-y divide-gray-200">
547
+ {items.map((item) => (
548
+ <tr key={item.id} className="hover:bg-gray-50">
549
+ ${tableCells}
550
+ <td className="px-4 py-2 text-right space-x-2">
551
+ <button onClick={() => onEdit(item)} className="text-blue-600 hover:text-blue-800 text-sm">Edit</button>
552
+ <button onClick={() => onDelete(item.id)} className="text-red-600 hover:text-red-800 text-sm">Delete</button>
553
+ </td>
554
+ </tr>
555
+ ))}
556
+ </tbody>
557
+ </table>
558
+ </div>
559
+ )
560
+ }
561
+ `,
562
+ });
563
+ // Form component
564
+ const formFields = fields.filter(f => f.name !== "id").map(f => {
565
+ const inputType = f.type === "number" || f.type === "integer" || f.type === "float" ? "number" : "text";
566
+ return ` <div>
567
+ <label className="block text-sm font-medium text-gray-700 mb-1">${f.name}</label>
568
+ <input
569
+ type="${inputType}"
570
+ name="${f.name}"
571
+ defaultValue={initialValues?.${f.name} ?? ""}
572
+ onChange={handleChange}
573
+ className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
574
+ />
575
+ </div>`;
576
+ }).join("\n\n");
577
+ files.push({
578
+ path: `src/client/components/${name}Form.tsx`,
579
+ description: `${name} form component`,
580
+ content: `import { useState, type FormEvent, type ChangeEvent } from "react"
581
+ import type { ${name} } from "../hooks/use${name}.js"
582
+
583
+ interface ${name}FormProps {
584
+ initialValues?: Partial<${name}>
585
+ onSubmit: (data: Record<string, unknown>) => Promise<void>
586
+ onCancel: () => void
587
+ }
588
+
589
+ export function ${name}Form({ initialValues, onSubmit, onCancel }: ${name}FormProps) {
590
+ const [values, setValues] = useState<Record<string, unknown>>(initialValues || {})
591
+ const [submitting, setSubmitting] = useState(false)
592
+
593
+ const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
594
+ setValues(prev => ({ ...prev, [e.target.name]: e.target.value }))
595
+ }
596
+
597
+ const handleSubmit = async (e: FormEvent) => {
598
+ e.preventDefault()
599
+ setSubmitting(true)
600
+ try { await onSubmit(values) } finally { setSubmitting(false) }
601
+ }
602
+
603
+ return (
604
+ <form onSubmit={handleSubmit} className="space-y-4 p-4 bg-white rounded-lg shadow">
605
+ ${formFields}
606
+ <div className="flex justify-end space-x-2">
607
+ <button type="button" onClick={onCancel} className="px-4 py-2 text-gray-600 hover:text-gray-800">Cancel</button>
608
+ <button type="submit" disabled={submitting} className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700 disabled:opacity-50">
609
+ {submitting ? "Saving..." : "Save"}
610
+ </button>
611
+ </div>
612
+ </form>
613
+ )
614
+ }
615
+ `,
616
+ });
617
+ // Page
618
+ files.push({
619
+ path: `src/client/pages/${name}Page.tsx`,
620
+ description: `${name} page (full CRUD)`,
621
+ content: `import { useState } from "react"
622
+ import { use${namePlural.charAt(0).toUpperCase() + namePlural.slice(1)} } from "../hooks/use${name}.js"
623
+ import { ${name}List } from "../components/${name}List.js"
624
+ import { ${name}Form } from "../components/${name}Form.js"
625
+ import type { ${name} } from "../hooks/use${name}.js"
626
+
627
+ export function ${name}Page() {
628
+ const { items, loading, error, create, update, remove } = use${namePlural.charAt(0).toUpperCase() + namePlural.slice(1)}()
629
+ const [editing, setEditing] = useState<${name} | null>(null)
630
+ const [showForm, setShowForm] = useState(false)
631
+
632
+ const handleCreate = async (data: Record<string, unknown>) => {
633
+ await create(data as any)
634
+ setShowForm(false)
635
+ }
636
+
637
+ const handleUpdate = async (data: Record<string, unknown>) => {
638
+ if (editing) {
639
+ await update(editing.id, data as any)
640
+ setEditing(null)
641
+ }
642
+ }
643
+
644
+ const handleDelete = async (id: string) => {
645
+ if (confirm("Are you sure?")) await remove(id)
646
+ }
647
+
648
+ if (loading) return <div className="p-8 text-center">Loading...</div>
649
+ if (error) return <div className="p-8 text-center text-red-600">Error: {error}</div>
650
+
651
+ return (
652
+ <div className="max-w-6xl mx-auto p-8">
653
+ <div className="flex justify-between items-center mb-6">
654
+ <h1 className="text-2xl font-bold text-gray-900">${name}</h1>
655
+ <button onClick={() => { setEditing(null); setShowForm(true) }} className="px-4 py-2 bg-blue-600 text-white rounded-md hover:bg-blue-700">
656
+ Add ${name}
657
+ </button>
658
+ </div>
659
+
660
+ {showForm && (
661
+ <${name}Form onSubmit={handleCreate} onCancel={() => setShowForm(false)} />
662
+ )}
663
+
664
+ {editing && (
665
+ <${name}Form initialValues={editing} onSubmit={handleUpdate} onCancel={() => setEditing(null)} />
666
+ )}
667
+
668
+ <${name}List items={items} onEdit={(item) => { setEditing(item); setShowForm(false) }} onDelete={handleDelete} />
669
+ </div>
670
+ )
671
+ }
672
+ `,
673
+ });
674
+ }
675
+ // App.tsx
676
+ const pageImports = entities.map(e => `import { ${e.name}Page } from "./pages/${e.name}Page.js"`).join("\n");
677
+ const pageRoutes = entities.map(e => {
678
+ const nameLower = e.name.toLowerCase();
679
+ const namePlural = `${nameLower}s`;
680
+ return ` <Route path="/${namePlural}" element={<${e.name}Page />} />`;
681
+ }).join("\n");
682
+ files.push({
683
+ path: "src/client/App.tsx",
684
+ description: "Main App component with routing",
685
+ content: `import { BrowserRouter, Routes, Route, Link } from "react-router-dom"
686
+ ${pageImports}
687
+
688
+ function Home() {
689
+ return (
690
+ <div className="max-w-4xl mx-auto p-8">
691
+ <h1 className="text-3xl font-bold mb-6">${graph.project_id}</h1>
692
+ <nav className="space-y-2">
693
+ ${entities.map(e => ` <Link to="/${e.name.toLowerCase()}s" className="block text-blue-600 hover:underline">${e.name}</Link>`).join("\n")}
694
+ </nav>
695
+ </div>
696
+ )
697
+ }
698
+
699
+ export default function App() {
700
+ return (
701
+ <BrowserRouter>
702
+ <div className="min-h-screen bg-gray-100">
703
+ <nav className="bg-white shadow-sm">
704
+ <div className="max-w-6xl mx-auto px-4 py-3">
705
+ <Link to="/" className="text-lg font-bold text-gray-900">${graph.project_id}</Link>
706
+ </div>
707
+ </nav>
708
+ <Routes>
709
+ <Route path="/" element={<Home />} />
710
+ ${pageRoutes}
711
+ </Routes>
712
+ </div>
713
+ </BrowserRouter>
714
+ )
715
+ }
716
+ `,
717
+ });
718
+ }
719
+ function generateDatabaseSchema(_graph, entities, _tables, files, dirs, stack) {
720
+ dirs.add("src/server");
721
+ if (stack.database === "sqlite" || stack.database === "postgresql" || stack.database === "mysql") {
722
+ const createStatements = entities.map(entity => {
723
+ const name = entity.name.toLowerCase();
724
+ const namePlural = `${name}s`;
725
+ const fields = entity.metadata.fields || [];
726
+ const columns = [
727
+ " id TEXT PRIMARY KEY",
728
+ ...fields.map(f => {
729
+ const colType = mapToSqlType(f.type);
730
+ const nullable = f.required ? " NOT NULL" : "";
731
+ const unique = f.unique ? " UNIQUE" : "";
732
+ return ` ${f.name} ${colType}${nullable}${unique}`;
733
+ }),
734
+ " created_at TEXT NOT NULL",
735
+ " updated_at TEXT NOT NULL",
736
+ ];
737
+ return `CREATE TABLE IF NOT EXISTS ${namePlural} (\n${columns.join(",\n")}\n);`;
738
+ });
739
+ files.push({
740
+ path: "src/server/schema.sql",
741
+ description: "Database schema",
742
+ content: createStatements.join("\n\n") + "\n",
743
+ });
744
+ // Database connection - built as array to avoid template literal nesting
745
+ if (stack.database === "sqlite") {
746
+ const dbLines = [
747
+ 'import Database from "bun:sqlite"',
748
+ "",
749
+ 'const sqlite = new Database(":memory:")',
750
+ "",
751
+ "export const db = {",
752
+ " select() {",
753
+ " return {",
754
+ " from: (table: string) => ({",
755
+ " where: (conditions: Record<string, unknown>) => ({",
756
+ " first: () => {",
757
+ " const keys = Object.keys(conditions)",
758
+ " const vals = Object.values(conditions)",
759
+ ' const placeholders = keys.map(k => k + " = ?").join(" AND ")',
760
+ " const stmt = sqlite.prepare(`SELECT * FROM ${" + "table" + "} WHERE ${" + "placeholders" + "}`)",
761
+ " return stmt.get(...vals) as any",
762
+ " },",
763
+ " }),",
764
+ " all: () => sqlite.prepare(`SELECT * FROM ${" + "table" + "}`).all() as any[],",
765
+ " }),",
766
+ " }",
767
+ " },",
768
+ "",
769
+ " insert(table: string) {",
770
+ " return {",
771
+ " values: (data: Record<string, unknown>) => {",
772
+ " const keys = Object.keys(data)",
773
+ " const vals = Object.values(data)",
774
+ ' const placeholders = keys.map(() => "?").join(", ")',
775
+ " const stmt = sqlite.prepare(`INSERT INTO ${" + "table" + "} (${" + "keys.join(', ')" + "}) VALUES (${" + "placeholders" + "}`)",
776
+ " return stmt.run(...vals)",
777
+ " },",
778
+ " }",
779
+ " },",
780
+ "",
781
+ " update(table: string) {",
782
+ " return {",
783
+ " set: (data: Record<string, unknown>) => ({",
784
+ " where: (conditions: Record<string, unknown>) => {",
785
+ " const setKeys = Object.keys(data)",
786
+ " const setVals = Object.values(data)",
787
+ " const whereKeys = Object.keys(conditions)",
788
+ " const whereVals = Object.values(conditions)",
789
+ ' const setClause = setKeys.map(k => k + " = ?").join(", ")',
790
+ ' const whereClause = whereKeys.map(k => k + " = ?").join(" AND ")',
791
+ " const stmt = sqlite.prepare(`UPDATE ${" + "table" + "} SET ${" + "setClause" + "} WHERE ${" + "whereClause" + "}`)",
792
+ " return stmt.run(...setVals, ...whereVals)",
793
+ " },",
794
+ " }),",
795
+ " }",
796
+ " },",
797
+ "",
798
+ " delete(table: string) {",
799
+ " return {",
800
+ " where: (conditions: Record<string, unknown>) => {",
801
+ " const keys = Object.keys(conditions)",
802
+ " const vals = Object.values(conditions)",
803
+ ' const placeholders = keys.map(k => k + " = ?").join(" AND ")',
804
+ " const stmt = sqlite.prepare(`DELETE FROM ${" + "table" + "} WHERE ${" + "placeholders" + "}`)",
805
+ " return { changes: stmt.run(...vals).changes }",
806
+ " },",
807
+ " }",
808
+ " },",
809
+ "}",
810
+ "",
811
+ "}",
812
+ ];
813
+ files.push({
814
+ path: "src/server/database.ts",
815
+ description: "SQLite database connection",
816
+ content: dbLines.join("\n"),
817
+ });
818
+ }
819
+ }
820
+ }
821
+ function generateTests(_graph, entities, _endpoints, files, dirs, _stack) {
822
+ dirs.add("tests");
823
+ for (const entity of entities) {
824
+ const name = entity.name;
825
+ const nameLower = name.toLowerCase();
826
+ const namePlural = `${nameLower}s`;
827
+ files.push({
828
+ path: `tests/${nameLower}.test.ts`,
829
+ description: `${name} API tests`,
830
+ content: `import { describe, test, expect, beforeAll, afterAll } from "bun:test"
831
+
832
+ const API = "http://localhost:3000/api"
833
+
834
+ describe("${name} API", () => {
835
+ let createdId: string
836
+
837
+ test("POST /${namePlural} - creates ${nameLower}", async () => {
838
+ const res = await fetch(\`\${API}/${namePlural}\`, {
839
+ method: "POST",
840
+ headers: { "Content-Type": "application/json" },
841
+ body: JSON.stringify({}),
842
+ })
843
+ expect(res.status).toBe(201)
844
+ const data = await res.json()
845
+ expect(data.id).toBeDefined()
846
+ createdId = data.id
847
+ })
848
+
849
+ test("GET /${namePlural} - lists ${namePlural}", async () => {
850
+ const res = await fetch(\`\${API}/${namePlural}\`)
851
+ expect(res.status).toBe(200)
852
+ const data = await res.json()
853
+ expect(Array.isArray(data)).toBe(true)
854
+ })
855
+
856
+ test("GET /${namePlural}/:id - gets ${nameLower}", async () => {
857
+ const res = await fetch(\`\${API}/${namePlural}/\${createdId}\`)
858
+ expect(res.status).toBe(200)
859
+ const data = await res.json()
860
+ expect(data.id).toBe(createdId)
861
+ })
862
+
863
+ test("PUT /${namePlural}/:id - updates ${nameLower}", async () => {
864
+ const res = await fetch(\`\${API}/${namePlural}/\${createdId}\`, {
865
+ method: "PUT",
866
+ headers: { "Content-Type": "application/json" },
867
+ body: JSON.stringify({}),
868
+ })
869
+ expect(res.status).toBe(200)
870
+ })
871
+
872
+ test("DELETE /${namePlural}/:id - deletes ${nameLower}", async () => {
873
+ const res = await fetch(\`\${API}/${namePlural}/\${createdId}\`, {
874
+ method: "DELETE",
875
+ })
876
+ expect(res.status).toBe(204)
877
+ })
878
+
879
+ test("GET /${namePlural}/:id - returns 404 for deleted", async () => {
880
+ const res = await fetch(\`\${API}/${namePlural}/\${createdId}\`)
881
+ expect(res.status).toBe(404)
882
+ })
883
+ })
884
+ `,
885
+ });
886
+ }
887
+ }
888
+ function generateSharedTypes(_graph, entities, files, dirs, _stack) {
889
+ dirs.add("src/shared");
890
+ const typeDefs = entities.map(entity => {
891
+ const fields = entity.metadata.fields || [];
892
+ const fieldDefs = fields.map(f => ` ${f.name}: ${mapToTsType(f.type)}`).join("\n");
893
+ return `export interface ${entity.name} {
894
+ id: string
895
+ ${fieldDefs}
896
+ created_at: string
897
+ updated_at: string
898
+ }`;
899
+ });
900
+ files.push({
901
+ path: "src/shared/types.ts",
902
+ description: "Shared type definitions",
903
+ content: typeDefs.join("\n\n") + "\n",
904
+ });
905
+ }
906
+ function mapToTsType(fieldType) {
907
+ const lower = fieldType.toLowerCase();
908
+ if (lower === "string" || lower === "text" || lower === "varchar")
909
+ return "string";
910
+ if (lower === "number" || lower === "integer" || lower === "int" || lower === "float" || lower === "decimal")
911
+ return "number";
912
+ if (lower === "boolean" || lower === "bool")
913
+ return "boolean";
914
+ if (lower === "date" || lower === "timestamp" || lower === "datetime")
915
+ return "string";
916
+ if (lower === "json" || lower === "object")
917
+ return "Record<string, unknown>";
918
+ if (lower === "uuid")
919
+ return "string";
920
+ return "string";
921
+ }
922
+ function mapToSqlType(fieldType) {
923
+ const lower = fieldType.toLowerCase();
924
+ if (lower === "string" || lower === "text" || lower === "varchar")
925
+ return "TEXT";
926
+ if (lower === "number" || lower === "integer" || lower === "int")
927
+ return "INTEGER";
928
+ if (lower === "float" || lower === "decimal")
929
+ return "REAL";
930
+ if (lower === "boolean" || lower === "bool")
931
+ return "INTEGER";
932
+ if (lower === "date" || lower === "timestamp" || lower === "datetime")
933
+ return "TEXT";
934
+ if (lower === "json" || lower === "object")
935
+ return "TEXT";
936
+ if (lower === "uuid")
937
+ return "TEXT";
938
+ return "TEXT";
939
+ }
940
+ function buildGenerationSummary(graph, entities, features, files, stack) {
941
+ const lines = [
942
+ "## Code Generation Summary",
943
+ "",
944
+ `**Project:** ${graph.project_id}`,
945
+ `**Stack:** ${stack.language} | ${stack.frontend} | ${stack.backend} | ${stack.database}`,
946
+ "",
947
+ "### Generated",
948
+ `- ${files.length} files`,
949
+ `- ${entities.length} entities`,
950
+ `- ${features.length} features`,
951
+ "",
952
+ "### Files",
953
+ ];
954
+ for (const f of files) {
955
+ lines.push(`- \`${f.path}\` — ${f.description}`);
956
+ }
957
+ return lines.join("\n");
958
+ }
959
+ /**
960
+ * Materialize a plan without silently destroying brownfield code. The caller
961
+ * receives all conflicts and must explicitly request overwrite after review.
962
+ */
963
+ export function writeGeneratedFiles(projectDir, plan, options = {}) {
964
+ let written = 0;
965
+ let created = 0;
966
+ let unchanged = 0;
967
+ const conflicts = [];
968
+ const backups = [];
969
+ const errors = [];
970
+ for (const dir of plan.directories) {
971
+ const fullPath = resolve(projectDir, dir);
972
+ if (relative(projectDir, fullPath).startsWith("..")) {
973
+ errors.push(`Refusing to create directory outside target: ${dir}`);
974
+ continue;
975
+ }
976
+ if (!existsSync(fullPath)) {
977
+ try {
978
+ mkdirSync(fullPath, { recursive: true });
979
+ }
980
+ catch (e) {
981
+ errors.push(`Failed to create directory ${dir}: ${e}`);
982
+ }
983
+ }
984
+ }
985
+ for (const file of plan.files) {
986
+ const fullPath = resolve(projectDir, file.path);
987
+ try {
988
+ if (relative(projectDir, fullPath).startsWith("..")) {
989
+ errors.push(`Refusing to write outside target: ${file.path}`);
990
+ continue;
991
+ }
992
+ const dir = dirname(fullPath);
993
+ if (!existsSync(dir))
994
+ mkdirSync(dir, { recursive: true });
995
+ if (existsSync(fullPath)) {
996
+ const current = require("fs").readFileSync(fullPath, "utf-8");
997
+ if (current === file.content) {
998
+ unchanged++;
999
+ continue;
1000
+ }
1001
+ if (!options.overwrite) {
1002
+ conflicts.push(file.path);
1003
+ continue;
1004
+ }
1005
+ if (options.backup !== false) {
1006
+ const backupPath = `${fullPath}.opencode-telos-backup-${Date.now()}`;
1007
+ writeFileSync(backupPath, current, "utf-8");
1008
+ backups.push(backupPath);
1009
+ }
1010
+ }
1011
+ else {
1012
+ created++;
1013
+ }
1014
+ writeFileSync(fullPath, file.content, "utf-8");
1015
+ written++;
1016
+ }
1017
+ catch (e) {
1018
+ errors.push(`Failed to write ${file.path}: ${e}`);
1019
+ }
1020
+ }
1021
+ return { written, created, unchanged, conflicts, backups, errors };
1022
+ }
1023
+ //# sourceMappingURL=generator.js.map