@memoarchitect/tools 0.6.7 → 0.8.7

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 (549) hide show
  1. package/README.md +36 -11
  2. package/corpus/README.md +63 -0
  3. package/corpus/sysml-v2-release/bnf/SysML-graphical-bnf.kgbnf +2264 -0
  4. package/package.json +20 -7
  5. package/packages/tools/lib/analysis/dsm.d.ts +1 -1
  6. package/packages/tools/lib/analysis/dsm.d.ts.map +1 -1
  7. package/packages/tools/lib/analysis/dsm.js +1 -1
  8. package/packages/tools/lib/analysis/dsm.js.map +1 -1
  9. package/packages/tools/lib/bin/memo.js +186 -10
  10. package/packages/tools/lib/bin/memo.js.map +1 -1
  11. package/packages/tools/lib/browser/index.d.ts +3 -1
  12. package/packages/tools/lib/browser/index.d.ts.map +1 -1
  13. package/packages/tools/lib/browser/index.js +2 -1
  14. package/packages/tools/lib/browser/index.js.map +1 -1
  15. package/packages/tools/lib/commands/ask.js +1 -1
  16. package/packages/tools/lib/commands/ask.js.map +1 -1
  17. package/packages/tools/lib/commands/check.d.ts.map +1 -1
  18. package/packages/tools/lib/commands/check.js +3 -9
  19. package/packages/tools/lib/commands/check.js.map +1 -1
  20. package/packages/tools/lib/commands/conformance.d.ts +36 -0
  21. package/packages/tools/lib/commands/conformance.d.ts.map +1 -0
  22. package/packages/tools/lib/commands/conformance.js +212 -0
  23. package/packages/tools/lib/commands/conformance.js.map +1 -0
  24. package/packages/tools/lib/commands/convert.d.ts +12 -0
  25. package/packages/tools/lib/commands/convert.d.ts.map +1 -0
  26. package/packages/tools/lib/commands/convert.js +103 -0
  27. package/packages/tools/lib/commands/convert.js.map +1 -0
  28. package/packages/tools/lib/commands/create-package.d.ts +1 -2
  29. package/packages/tools/lib/commands/create-package.d.ts.map +1 -1
  30. package/packages/tools/lib/commands/create-package.js.map +1 -1
  31. package/packages/tools/lib/commands/dev.d.ts +13 -0
  32. package/packages/tools/lib/commands/dev.d.ts.map +1 -1
  33. package/packages/tools/lib/commands/dev.js +245 -89
  34. package/packages/tools/lib/commands/dev.js.map +1 -1
  35. package/packages/tools/lib/commands/dhf-draft.js +1 -1
  36. package/packages/tools/lib/commands/dhf-draft.js.map +1 -1
  37. package/packages/tools/lib/commands/dhf-lint.d.ts +10 -0
  38. package/packages/tools/lib/commands/dhf-lint.d.ts.map +1 -0
  39. package/packages/tools/lib/commands/dhf-lint.js +72 -0
  40. package/packages/tools/lib/commands/dhf-lint.js.map +1 -0
  41. package/packages/tools/lib/commands/dhf-preview.js +1 -1
  42. package/packages/tools/lib/commands/dhf-preview.js.map +1 -1
  43. package/packages/tools/lib/commands/dhf.d.ts.map +1 -1
  44. package/packages/tools/lib/commands/dhf.js +8 -2
  45. package/packages/tools/lib/commands/dhf.js.map +1 -1
  46. package/packages/tools/lib/commands/element.d.ts +34 -0
  47. package/packages/tools/lib/commands/element.d.ts.map +1 -0
  48. package/packages/tools/lib/commands/element.js +174 -0
  49. package/packages/tools/lib/commands/element.js.map +1 -0
  50. package/packages/tools/lib/commands/export.d.ts.map +1 -1
  51. package/packages/tools/lib/commands/export.js +39 -40
  52. package/packages/tools/lib/commands/export.js.map +1 -1
  53. package/packages/tools/lib/commands/generate.d.ts.map +1 -1
  54. package/packages/tools/lib/commands/generate.js +10 -7
  55. package/packages/tools/lib/commands/generate.js.map +1 -1
  56. package/packages/tools/lib/commands/import.d.ts.map +1 -1
  57. package/packages/tools/lib/commands/import.js +25 -12
  58. package/packages/tools/lib/commands/import.js.map +1 -1
  59. package/packages/tools/lib/commands/init.d.ts.map +1 -1
  60. package/packages/tools/lib/commands/init.js +34 -14
  61. package/packages/tools/lib/commands/init.js.map +1 -1
  62. package/packages/tools/lib/commands/inspect.d.ts +5 -0
  63. package/packages/tools/lib/commands/inspect.d.ts.map +1 -0
  64. package/packages/tools/lib/commands/inspect.js +56 -0
  65. package/packages/tools/lib/commands/inspect.js.map +1 -0
  66. package/packages/tools/lib/commands/lock.d.ts.map +1 -1
  67. package/packages/tools/lib/commands/lock.js +7 -2
  68. package/packages/tools/lib/commands/lock.js.map +1 -1
  69. package/packages/tools/lib/commands/ontology.d.ts.map +1 -1
  70. package/packages/tools/lib/commands/ontology.js +69 -116
  71. package/packages/tools/lib/commands/ontology.js.map +1 -1
  72. package/packages/tools/lib/commands/pack.d.ts +1 -1
  73. package/packages/tools/lib/commands/pack.d.ts.map +1 -1
  74. package/packages/tools/lib/commands/pack.js +20 -78
  75. package/packages/tools/lib/commands/pack.js.map +1 -1
  76. package/packages/tools/lib/commands/package.d.ts +10 -0
  77. package/packages/tools/lib/commands/package.d.ts.map +1 -0
  78. package/packages/tools/lib/commands/package.js +113 -0
  79. package/packages/tools/lib/commands/package.js.map +1 -0
  80. package/packages/tools/lib/commands/plugin.js +1 -1
  81. package/packages/tools/lib/commands/plugin.js.map +1 -1
  82. package/packages/tools/lib/commands/rules.d.ts.map +1 -1
  83. package/packages/tools/lib/commands/rules.js +120 -30
  84. package/packages/tools/lib/commands/rules.js.map +1 -1
  85. package/packages/tools/lib/commands/standards.d.ts +28 -0
  86. package/packages/tools/lib/commands/standards.d.ts.map +1 -0
  87. package/packages/tools/lib/commands/standards.js +203 -0
  88. package/packages/tools/lib/commands/standards.js.map +1 -0
  89. package/packages/tools/lib/commands/sysand-publish.d.ts.map +1 -1
  90. package/packages/tools/lib/commands/sysand-publish.js +14 -16
  91. package/packages/tools/lib/commands/sysand-publish.js.map +1 -1
  92. package/packages/tools/lib/commands/toolchain.d.ts +8 -0
  93. package/packages/tools/lib/commands/toolchain.d.ts.map +1 -0
  94. package/packages/tools/lib/commands/toolchain.js +64 -0
  95. package/packages/tools/lib/commands/toolchain.js.map +1 -0
  96. package/packages/tools/lib/commands/validate.d.ts +1 -1
  97. package/packages/tools/lib/commands/validate.d.ts.map +1 -1
  98. package/packages/tools/lib/commands/validate.js +194 -56
  99. package/packages/tools/lib/commands/validate.js.map +1 -1
  100. package/packages/tools/lib/completeness/tracker.d.ts +10 -2
  101. package/packages/tools/lib/completeness/tracker.d.ts.map +1 -1
  102. package/packages/tools/lib/completeness/tracker.js +16 -21
  103. package/packages/tools/lib/completeness/tracker.js.map +1 -1
  104. package/packages/tools/lib/conformance/baseline.d.ts +26 -0
  105. package/packages/tools/lib/conformance/baseline.d.ts.map +1 -0
  106. package/packages/tools/lib/conformance/baseline.js +170 -0
  107. package/packages/tools/lib/conformance/baseline.js.map +1 -0
  108. package/packages/tools/lib/conformance/bnf.d.ts +84 -0
  109. package/packages/tools/lib/conformance/bnf.d.ts.map +1 -0
  110. package/packages/tools/lib/conformance/bnf.js +166 -0
  111. package/packages/tools/lib/conformance/bnf.js.map +1 -0
  112. package/packages/tools/lib/conformance/corpus.d.ts +125 -0
  113. package/packages/tools/lib/conformance/corpus.d.ts.map +1 -0
  114. package/packages/tools/lib/conformance/corpus.js +190 -0
  115. package/packages/tools/lib/conformance/corpus.js.map +1 -0
  116. package/packages/tools/lib/conformance/diff-xmi.d.ts +118 -0
  117. package/packages/tools/lib/conformance/diff-xmi.d.ts.map +1 -0
  118. package/packages/tools/lib/conformance/diff-xmi.js +276 -0
  119. package/packages/tools/lib/conformance/diff-xmi.js.map +1 -0
  120. package/packages/tools/lib/conformance/generated/syside-rules.d.ts +10 -0
  121. package/packages/tools/lib/conformance/generated/syside-rules.d.ts.map +1 -0
  122. package/packages/tools/lib/conformance/generated/syside-rules.js +1142 -0
  123. package/packages/tools/lib/conformance/generated/syside-rules.js.map +1 -0
  124. package/packages/tools/lib/conformance/index.d.ts +7 -0
  125. package/packages/tools/lib/conformance/index.d.ts.map +1 -0
  126. package/packages/tools/lib/conformance/index.js +19 -0
  127. package/packages/tools/lib/conformance/index.js.map +1 -0
  128. package/packages/tools/lib/conformance/run.d.ts +117 -0
  129. package/packages/tools/lib/conformance/run.d.ts.map +1 -0
  130. package/packages/tools/lib/conformance/run.js +0 -0
  131. package/packages/tools/lib/conformance/run.js.map +1 -0
  132. package/packages/tools/lib/conformance/xmi.d.ts +45 -0
  133. package/packages/tools/lib/conformance/xmi.d.ts.map +1 -0
  134. package/packages/tools/lib/conformance/xmi.js +148 -0
  135. package/packages/tools/lib/conformance/xmi.js.map +1 -0
  136. package/packages/tools/lib/dhf/document-compiler.d.ts.map +1 -1
  137. package/packages/tools/lib/dhf/document-compiler.js +13 -8
  138. package/packages/tools/lib/dhf/document-compiler.js.map +1 -1
  139. package/packages/tools/lib/dhf/document-registry.d.ts +16 -2
  140. package/packages/tools/lib/dhf/document-registry.d.ts.map +1 -1
  141. package/packages/tools/lib/dhf/document-registry.js +74 -23
  142. package/packages/tools/lib/dhf/document-registry.js.map +1 -1
  143. package/packages/tools/lib/dhf/index.d.ts +3 -0
  144. package/packages/tools/lib/dhf/index.d.ts.map +1 -1
  145. package/packages/tools/lib/dhf/index.js +4 -0
  146. package/packages/tools/lib/dhf/index.js.map +1 -1
  147. package/packages/tools/lib/dhf/query-engine.d.ts +12 -1
  148. package/packages/tools/lib/dhf/query-engine.d.ts.map +1 -1
  149. package/packages/tools/lib/dhf/query-engine.js +2 -1
  150. package/packages/tools/lib/dhf/query-engine.js.map +1 -1
  151. package/packages/tools/lib/dhf/query-executor.d.ts +72 -5
  152. package/packages/tools/lib/dhf/query-executor.d.ts.map +1 -1
  153. package/packages/tools/lib/dhf/query-executor.js +471 -81
  154. package/packages/tools/lib/dhf/query-executor.js.map +1 -1
  155. package/packages/tools/lib/dhf/script-runner.js +6 -6
  156. package/packages/tools/lib/dhf/script-runner.js.map +1 -1
  157. package/packages/tools/lib/dhf/standards-block.d.ts +40 -0
  158. package/packages/tools/lib/dhf/standards-block.d.ts.map +1 -0
  159. package/packages/tools/lib/dhf/standards-block.js +223 -0
  160. package/packages/tools/lib/dhf/standards-block.js.map +1 -0
  161. package/packages/tools/lib/dhf/standards-library.d.ts +123 -0
  162. package/packages/tools/lib/dhf/standards-library.d.ts.map +1 -0
  163. package/packages/tools/lib/dhf/standards-library.js +295 -0
  164. package/packages/tools/lib/dhf/standards-library.js.map +1 -0
  165. package/packages/tools/lib/dhf/standards-report.d.ts +189 -0
  166. package/packages/tools/lib/dhf/standards-report.d.ts.map +1 -0
  167. package/packages/tools/lib/dhf/standards-report.js +384 -0
  168. package/packages/tools/lib/dhf/standards-report.js.map +1 -0
  169. package/packages/tools/lib/dhf/template-lint.d.ts +42 -0
  170. package/packages/tools/lib/dhf/template-lint.d.ts.map +1 -0
  171. package/packages/tools/lib/dhf/template-lint.js +421 -0
  172. package/packages/tools/lib/dhf/template-lint.js.map +1 -0
  173. package/packages/tools/lib/dhf/template-resolver.d.ts.map +1 -1
  174. package/packages/tools/lib/dhf/template-resolver.js +18 -6
  175. package/packages/tools/lib/dhf/template-resolver.js.map +1 -1
  176. package/packages/tools/lib/import/column-mapper.d.ts +2 -2
  177. package/packages/tools/lib/import/column-mapper.d.ts.map +1 -1
  178. package/packages/tools/lib/import/column-mapper.js +3 -3
  179. package/packages/tools/lib/import/column-mapper.js.map +1 -1
  180. package/packages/tools/lib/importer/cameo-importer.js +2 -2
  181. package/packages/tools/lib/importer/cameo-importer.js.map +1 -1
  182. package/packages/tools/lib/importer/ea-importer.d.ts.map +1 -1
  183. package/packages/tools/lib/importer/ea-importer.js +4 -3
  184. package/packages/tools/lib/importer/ea-importer.js.map +1 -1
  185. package/packages/tools/lib/importer/owl-importer.d.ts.map +1 -1
  186. package/packages/tools/lib/importer/owl-importer.js +2 -3
  187. package/packages/tools/lib/importer/owl-importer.js.map +1 -1
  188. package/packages/tools/lib/index.d.ts +20 -3
  189. package/packages/tools/lib/index.d.ts.map +1 -1
  190. package/packages/tools/lib/index.js +19 -2
  191. package/packages/tools/lib/index.js.map +1 -1
  192. package/packages/tools/lib/language/generated/ast.d.ts +1344 -99
  193. package/packages/tools/lib/language/generated/ast.d.ts.map +1 -1
  194. package/packages/tools/lib/language/generated/ast.js +1066 -32
  195. package/packages/tools/lib/language/generated/ast.js.map +1 -1
  196. package/packages/tools/lib/language/generated/grammar.d.ts.map +1 -1
  197. package/packages/tools/lib/language/generated/grammar.js +5242 -1454
  198. package/packages/tools/lib/language/generated/grammar.js.map +1 -1
  199. package/packages/tools/lib/llm/chat-engine.d.ts +4 -3
  200. package/packages/tools/lib/llm/chat-engine.d.ts.map +1 -1
  201. package/packages/tools/lib/llm/chat-engine.js +15 -12
  202. package/packages/tools/lib/llm/chat-engine.js.map +1 -1
  203. package/packages/tools/lib/llm/generate-engine.d.ts +7 -2
  204. package/packages/tools/lib/llm/generate-engine.d.ts.map +1 -1
  205. package/packages/tools/lib/llm/generate-engine.js +22 -4
  206. package/packages/tools/lib/llm/generate-engine.js.map +1 -1
  207. package/packages/tools/lib/llm/index.d.ts +1 -0
  208. package/packages/tools/lib/llm/index.d.ts.map +1 -1
  209. package/packages/tools/lib/llm/index.js +1 -0
  210. package/packages/tools/lib/llm/index.js.map +1 -1
  211. package/packages/tools/lib/llm/model-context.d.ts +2 -2
  212. package/packages/tools/lib/llm/model-context.d.ts.map +1 -1
  213. package/packages/tools/lib/llm/model-context.js +7 -13
  214. package/packages/tools/lib/llm/model-context.js.map +1 -1
  215. package/packages/tools/lib/llm/sysml-guidance.d.ts +8 -0
  216. package/packages/tools/lib/llm/sysml-guidance.d.ts.map +1 -0
  217. package/packages/tools/lib/llm/sysml-guidance.js +28 -0
  218. package/packages/tools/lib/llm/sysml-guidance.js.map +1 -0
  219. package/packages/tools/lib/lock.d.ts +14 -8
  220. package/packages/tools/lib/lock.d.ts.map +1 -1
  221. package/packages/tools/lib/lock.js +97 -108
  222. package/packages/tools/lib/lock.js.map +1 -1
  223. package/packages/tools/lib/mcp/model-loader.d.ts +3 -0
  224. package/packages/tools/lib/mcp/model-loader.d.ts.map +1 -1
  225. package/packages/tools/lib/mcp/model-loader.js +9 -5
  226. package/packages/tools/lib/mcp/model-loader.js.map +1 -1
  227. package/packages/tools/lib/mcp/tools.d.ts +3 -0
  228. package/packages/tools/lib/mcp/tools.d.ts.map +1 -1
  229. package/packages/tools/lib/mcp/tools.js +8 -9
  230. package/packages/tools/lib/mcp/tools.js.map +1 -1
  231. package/packages/tools/lib/model/activity-notation.d.ts +54 -0
  232. package/packages/tools/lib/model/activity-notation.d.ts.map +1 -0
  233. package/packages/tools/lib/model/activity-notation.js +208 -0
  234. package/packages/tools/lib/model/activity-notation.js.map +1 -0
  235. package/packages/tools/lib/model/builder.d.ts +3 -0
  236. package/packages/tools/lib/model/builder.d.ts.map +1 -1
  237. package/packages/tools/lib/model/builder.js +956 -62
  238. package/packages/tools/lib/model/builder.js.map +1 -1
  239. package/packages/tools/lib/model/config-loader.d.ts +19 -25
  240. package/packages/tools/lib/model/config-loader.d.ts.map +1 -1
  241. package/packages/tools/lib/model/config-loader.js +51 -233
  242. package/packages/tools/lib/model/config-loader.js.map +1 -1
  243. package/packages/tools/lib/model/config.d.ts +42 -213
  244. package/packages/tools/lib/model/config.d.ts.map +1 -1
  245. package/packages/tools/lib/model/config.js +11 -9
  246. package/packages/tools/lib/model/config.js.map +1 -1
  247. package/packages/tools/lib/model/effective-scope.d.ts +74 -0
  248. package/packages/tools/lib/model/effective-scope.d.ts.map +1 -0
  249. package/packages/tools/lib/model/effective-scope.js +133 -0
  250. package/packages/tools/lib/model/effective-scope.js.map +1 -0
  251. package/packages/tools/lib/model/ir-identity.d.ts +94 -0
  252. package/packages/tools/lib/model/ir-identity.d.ts.map +1 -0
  253. package/packages/tools/lib/model/ir-identity.js +178 -0
  254. package/packages/tools/lib/model/ir-identity.js.map +1 -0
  255. package/packages/tools/lib/model/kind-registry.d.ts +134 -1
  256. package/packages/tools/lib/model/kind-registry.d.ts.map +1 -1
  257. package/packages/tools/lib/model/kind-registry.js +186 -4
  258. package/packages/tools/lib/model/kind-registry.js.map +1 -1
  259. package/packages/tools/lib/model/layer-resolver.js +1 -1
  260. package/packages/tools/lib/model/layer-resolver.js.map +1 -1
  261. package/packages/tools/lib/model/manifest.d.ts +8 -0
  262. package/packages/tools/lib/model/manifest.d.ts.map +1 -1
  263. package/packages/tools/lib/model/manifest.js +3 -0
  264. package/packages/tools/lib/model/manifest.js.map +1 -1
  265. package/packages/tools/lib/model/methodology-loader.d.ts +19 -24
  266. package/packages/tools/lib/model/methodology-loader.d.ts.map +1 -1
  267. package/packages/tools/lib/model/methodology-loader.js +179 -176
  268. package/packages/tools/lib/model/methodology-loader.js.map +1 -1
  269. package/packages/tools/lib/model/methodology-resolver.d.ts +115 -0
  270. package/packages/tools/lib/model/methodology-resolver.d.ts.map +1 -0
  271. package/packages/tools/lib/model/methodology-resolver.js +317 -0
  272. package/packages/tools/lib/model/methodology-resolver.js.map +1 -0
  273. package/packages/tools/lib/model/naming.d.ts +57 -0
  274. package/packages/tools/lib/model/naming.d.ts.map +1 -0
  275. package/packages/tools/lib/model/naming.js +69 -0
  276. package/packages/tools/lib/model/naming.js.map +1 -0
  277. package/packages/tools/lib/model/native-project.d.ts +130 -0
  278. package/packages/tools/lib/model/native-project.d.ts.map +1 -0
  279. package/packages/tools/lib/model/native-project.js +580 -0
  280. package/packages/tools/lib/model/native-project.js.map +1 -0
  281. package/packages/tools/lib/model/ontology-loader.d.ts +34 -21
  282. package/packages/tools/lib/model/ontology-loader.d.ts.map +1 -1
  283. package/packages/tools/lib/model/ontology-loader.js +343 -614
  284. package/packages/tools/lib/model/ontology-loader.js.map +1 -1
  285. package/packages/tools/lib/model/package-manifest.d.ts +37 -0
  286. package/packages/tools/lib/model/package-manifest.d.ts.map +1 -0
  287. package/packages/tools/lib/model/package-manifest.js +96 -0
  288. package/packages/tools/lib/model/package-manifest.js.map +1 -0
  289. package/packages/tools/lib/model/parser-utils.d.ts +31 -0
  290. package/packages/tools/lib/model/parser-utils.d.ts.map +1 -1
  291. package/packages/tools/lib/model/parser-utils.js +89 -1
  292. package/packages/tools/lib/model/parser-utils.js.map +1 -1
  293. package/packages/tools/lib/model/paths.d.ts +10 -4
  294. package/packages/tools/lib/model/paths.d.ts.map +1 -1
  295. package/packages/tools/lib/model/paths.js +10 -4
  296. package/packages/tools/lib/model/paths.js.map +1 -1
  297. package/packages/tools/lib/model/project-conversion.d.ts +226 -0
  298. package/packages/tools/lib/model/project-conversion.d.ts.map +1 -0
  299. package/packages/tools/lib/model/project-conversion.js +946 -0
  300. package/packages/tools/lib/model/project-conversion.js.map +1 -0
  301. package/packages/tools/lib/model/relationship-legality.d.ts +27 -0
  302. package/packages/tools/lib/model/relationship-legality.d.ts.map +1 -1
  303. package/packages/tools/lib/model/relationship-legality.js.map +1 -1
  304. package/packages/tools/lib/model/relationship-registry.d.ts +93 -1
  305. package/packages/tools/lib/model/relationship-registry.d.ts.map +1 -1
  306. package/packages/tools/lib/model/relationship-registry.js +217 -2
  307. package/packages/tools/lib/model/relationship-registry.js.map +1 -1
  308. package/packages/tools/lib/model/semantic.d.ts +73 -0
  309. package/packages/tools/lib/model/semantic.d.ts.map +1 -1
  310. package/packages/tools/lib/model/semantic.js +6 -0
  311. package/packages/tools/lib/model/semantic.js.map +1 -1
  312. package/packages/tools/lib/model/settings-boundary.d.ts +19 -0
  313. package/packages/tools/lib/model/settings-boundary.d.ts.map +1 -0
  314. package/packages/tools/lib/model/settings-boundary.js +118 -0
  315. package/packages/tools/lib/model/settings-boundary.js.map +1 -0
  316. package/packages/tools/lib/model/short-id.js +3 -3
  317. package/packages/tools/lib/model/short-id.js.map +1 -1
  318. package/packages/tools/lib/model/source-graph.d.ts.map +1 -1
  319. package/packages/tools/lib/model/source-graph.js +5 -1
  320. package/packages/tools/lib/model/source-graph.js.map +1 -1
  321. package/packages/tools/lib/model/source-provenance.d.ts +112 -0
  322. package/packages/tools/lib/model/source-provenance.d.ts.map +1 -0
  323. package/packages/tools/lib/model/source-provenance.js +169 -0
  324. package/packages/tools/lib/model/source-provenance.js.map +1 -0
  325. package/packages/tools/lib/model/sysml-ir.d.ts +9 -0
  326. package/packages/tools/lib/model/sysml-ir.d.ts.map +1 -0
  327. package/packages/tools/lib/model/sysml-ir.js +105 -0
  328. package/packages/tools/lib/model/sysml-ir.js.map +1 -0
  329. package/packages/tools/lib/model/view-deriver.d.ts +10 -1
  330. package/packages/tools/lib/model/view-deriver.d.ts.map +1 -1
  331. package/packages/tools/lib/model/view-deriver.js +139 -11
  332. package/packages/tools/lib/model/view-deriver.js.map +1 -1
  333. package/packages/tools/lib/model/view-kinds.d.ts +2 -0
  334. package/packages/tools/lib/model/view-kinds.d.ts.map +1 -1
  335. package/packages/tools/lib/model/view-kinds.js +11 -0
  336. package/packages/tools/lib/model/view-kinds.js.map +1 -1
  337. package/packages/tools/lib/ontology/owl-exporter.d.ts +2 -2
  338. package/packages/tools/lib/ontology/owl-exporter.d.ts.map +1 -1
  339. package/packages/tools/lib/ontology/owl-exporter.js +12 -12
  340. package/packages/tools/lib/ontology/owl-exporter.js.map +1 -1
  341. package/packages/tools/lib/operations/ai-authoring.d.ts +24 -0
  342. package/packages/tools/lib/operations/ai-authoring.d.ts.map +1 -0
  343. package/packages/tools/lib/operations/ai-authoring.js +77 -0
  344. package/packages/tools/lib/operations/ai-authoring.js.map +1 -0
  345. package/packages/tools/lib/operations/authoring.d.ts +40 -0
  346. package/packages/tools/lib/operations/authoring.d.ts.map +1 -0
  347. package/packages/tools/lib/operations/authoring.js +56 -0
  348. package/packages/tools/lib/operations/authoring.js.map +1 -0
  349. package/packages/tools/lib/operations/index.d.ts +2 -0
  350. package/packages/tools/lib/operations/index.d.ts.map +1 -1
  351. package/packages/tools/lib/operations/index.js +2 -0
  352. package/packages/tools/lib/operations/index.js.map +1 -1
  353. package/packages/tools/lib/operations/project-snapshot.d.ts +28 -3
  354. package/packages/tools/lib/operations/project-snapshot.d.ts.map +1 -1
  355. package/packages/tools/lib/operations/project-snapshot.js +79 -30
  356. package/packages/tools/lib/operations/project-snapshot.js.map +1 -1
  357. package/packages/tools/lib/protocol/messages.d.ts +381 -12
  358. package/packages/tools/lib/protocol/messages.d.ts.map +1 -1
  359. package/packages/tools/lib/serializer/csv-io.d.ts +7 -7
  360. package/packages/tools/lib/serializer/csv-io.d.ts.map +1 -1
  361. package/packages/tools/lib/serializer/csv-io.js +11 -11
  362. package/packages/tools/lib/serializer/csv-io.js.map +1 -1
  363. package/packages/tools/lib/serializer/sysml-generator.d.ts.map +1 -1
  364. package/packages/tools/lib/serializer/sysml-generator.js +34 -2
  365. package/packages/tools/lib/serializer/sysml-generator.js.map +1 -1
  366. package/packages/tools/lib/server/config-resolver.d.ts +8 -4
  367. package/packages/tools/lib/server/config-resolver.d.ts.map +1 -1
  368. package/packages/tools/lib/server/config-resolver.js +25 -44
  369. package/packages/tools/lib/server/config-resolver.js.map +1 -1
  370. package/packages/tools/lib/server/conflict-policy.d.ts +44 -0
  371. package/packages/tools/lib/server/conflict-policy.d.ts.map +1 -0
  372. package/packages/tools/lib/server/conflict-policy.js +94 -0
  373. package/packages/tools/lib/server/conflict-policy.js.map +1 -0
  374. package/packages/tools/lib/server/dev-server.d.ts +32 -2
  375. package/packages/tools/lib/server/dev-server.d.ts.map +1 -1
  376. package/packages/tools/lib/server/dev-server.js +875 -54
  377. package/packages/tools/lib/server/dev-server.js.map +1 -1
  378. package/packages/tools/lib/server/element-writer.d.ts +11 -0
  379. package/packages/tools/lib/server/element-writer.d.ts.map +1 -0
  380. package/packages/tools/lib/server/element-writer.js +123 -0
  381. package/packages/tools/lib/server/element-writer.js.map +1 -0
  382. package/packages/tools/lib/server/file-watcher.d.ts +4 -1
  383. package/packages/tools/lib/server/file-watcher.d.ts.map +1 -1
  384. package/packages/tools/lib/server/file-watcher.js +17 -7
  385. package/packages/tools/lib/server/file-watcher.js.map +1 -1
  386. package/packages/tools/lib/server/mutation-domain.d.ts +22 -0
  387. package/packages/tools/lib/server/mutation-domain.d.ts.map +1 -0
  388. package/packages/tools/lib/server/mutation-domain.js +87 -0
  389. package/packages/tools/lib/server/mutation-domain.js.map +1 -0
  390. package/packages/tools/lib/server/package-source.d.ts +26 -0
  391. package/packages/tools/lib/server/package-source.d.ts.map +1 -0
  392. package/packages/tools/lib/server/package-source.js +81 -0
  393. package/packages/tools/lib/server/package-source.js.map +1 -0
  394. package/packages/tools/lib/server/package-writer.d.ts +94 -0
  395. package/packages/tools/lib/server/package-writer.d.ts.map +1 -0
  396. package/packages/tools/lib/server/package-writer.js +317 -0
  397. package/packages/tools/lib/server/package-writer.js.map +1 -0
  398. package/packages/tools/lib/server/persistor.d.ts +81 -6
  399. package/packages/tools/lib/server/persistor.d.ts.map +1 -1
  400. package/packages/tools/lib/server/persistor.js +173 -44
  401. package/packages/tools/lib/server/persistor.js.map +1 -1
  402. package/packages/tools/lib/server/relationship-writer.d.ts +41 -5
  403. package/packages/tools/lib/server/relationship-writer.d.ts.map +1 -1
  404. package/packages/tools/lib/server/relationship-writer.js +157 -13
  405. package/packages/tools/lib/server/relationship-writer.js.map +1 -1
  406. package/packages/tools/lib/server/rule-policy-writer.d.ts +40 -0
  407. package/packages/tools/lib/server/rule-policy-writer.d.ts.map +1 -0
  408. package/packages/tools/lib/server/rule-policy-writer.js +124 -0
  409. package/packages/tools/lib/server/rule-policy-writer.js.map +1 -0
  410. package/packages/tools/lib/server/runtime-budget.d.ts +14 -0
  411. package/packages/tools/lib/server/runtime-budget.d.ts.map +1 -0
  412. package/packages/tools/lib/server/runtime-budget.js +15 -0
  413. package/packages/tools/lib/server/runtime-budget.js.map +1 -0
  414. package/packages/tools/lib/server/sysml-notation.d.ts +36 -0
  415. package/packages/tools/lib/server/sysml-notation.d.ts.map +1 -0
  416. package/packages/tools/lib/server/sysml-notation.js +104 -0
  417. package/packages/tools/lib/server/sysml-notation.js.map +1 -0
  418. package/packages/tools/lib/server/view-layout-store.d.ts.map +1 -1
  419. package/packages/tools/lib/server/view-layout-store.js +1 -0
  420. package/packages/tools/lib/server/view-layout-store.js.map +1 -1
  421. package/packages/tools/lib/sysml-ir/generated/sysml-derivations.d.ts +9 -0
  422. package/packages/tools/lib/sysml-ir/generated/sysml-derivations.d.ts.map +1 -0
  423. package/packages/tools/lib/sysml-ir/generated/sysml-derivations.js +315 -0
  424. package/packages/tools/lib/sysml-ir/generated/sysml-derivations.js.map +1 -0
  425. package/packages/tools/lib/sysml-ir/generated/sysml-metamodel.d.ts +5206 -0
  426. package/packages/tools/lib/sysml-ir/generated/sysml-metamodel.d.ts.map +1 -0
  427. package/packages/tools/lib/sysml-ir/generated/sysml-metamodel.js +1933 -0
  428. package/packages/tools/lib/sysml-ir/generated/sysml-metamodel.js.map +1 -0
  429. package/packages/tools/lib/sysml-ir/index.d.ts +3 -0
  430. package/packages/tools/lib/sysml-ir/index.d.ts.map +1 -0
  431. package/packages/tools/lib/sysml-ir/index.js +3 -0
  432. package/packages/tools/lib/sysml-ir/index.js.map +1 -0
  433. package/packages/tools/lib/sysml-ir/ir.d.ts +50 -0
  434. package/packages/tools/lib/sysml-ir/ir.d.ts.map +1 -0
  435. package/packages/tools/lib/sysml-ir/ir.js +2 -0
  436. package/packages/tools/lib/sysml-ir/ir.js.map +1 -0
  437. package/packages/tools/lib/sysmlc/bin/memo-sysmlc.d.ts +3 -0
  438. package/packages/tools/lib/sysmlc/bin/memo-sysmlc.d.ts.map +1 -0
  439. package/packages/tools/lib/sysmlc/bin/memo-sysmlc.js +97 -0
  440. package/packages/tools/lib/sysmlc/bin/memo-sysmlc.js.map +1 -0
  441. package/packages/tools/lib/sysmlc/index.d.ts +2 -0
  442. package/packages/tools/lib/sysmlc/index.d.ts.map +1 -0
  443. package/packages/tools/lib/sysmlc/index.js +7 -0
  444. package/packages/tools/lib/sysmlc/index.js.map +1 -0
  445. package/packages/tools/lib/sysmlc/server.d.ts +29 -0
  446. package/packages/tools/lib/sysmlc/server.d.ts.map +1 -0
  447. package/packages/tools/lib/sysmlc/server.js +168 -0
  448. package/packages/tools/lib/sysmlc/server.js.map +1 -0
  449. package/packages/tools/lib/toolchain/default-registry.d.ts +12 -0
  450. package/packages/tools/lib/toolchain/default-registry.d.ts.map +1 -0
  451. package/packages/tools/lib/toolchain/default-registry.js +28 -0
  452. package/packages/tools/lib/toolchain/default-registry.js.map +1 -0
  453. package/packages/tools/lib/toolchain/diagnostic.d.ts +57 -0
  454. package/packages/tools/lib/toolchain/diagnostic.d.ts.map +1 -0
  455. package/packages/tools/lib/toolchain/diagnostic.js +69 -0
  456. package/packages/tools/lib/toolchain/diagnostic.js.map +1 -0
  457. package/packages/tools/lib/toolchain/effective.d.ts +36 -0
  458. package/packages/tools/lib/toolchain/effective.d.ts.map +1 -0
  459. package/packages/tools/lib/toolchain/effective.js +91 -0
  460. package/packages/tools/lib/toolchain/effective.js.map +1 -0
  461. package/packages/tools/lib/toolchain/index.d.ts +11 -0
  462. package/packages/tools/lib/toolchain/index.d.ts.map +1 -0
  463. package/packages/tools/lib/toolchain/index.js +21 -0
  464. package/packages/tools/lib/toolchain/index.js.map +1 -0
  465. package/packages/tools/lib/toolchain/lowering.d.ts +63 -0
  466. package/packages/tools/lib/toolchain/lowering.d.ts.map +1 -0
  467. package/packages/tools/lib/toolchain/lowering.js +100 -0
  468. package/packages/tools/lib/toolchain/lowering.js.map +1 -0
  469. package/packages/tools/lib/toolchain/operations.d.ts +87 -0
  470. package/packages/tools/lib/toolchain/operations.d.ts.map +1 -0
  471. package/packages/tools/lib/toolchain/operations.js +111 -0
  472. package/packages/tools/lib/toolchain/operations.js.map +1 -0
  473. package/packages/tools/lib/toolchain/process.d.ts +45 -0
  474. package/packages/tools/lib/toolchain/process.d.ts.map +1 -0
  475. package/packages/tools/lib/toolchain/process.js +125 -0
  476. package/packages/tools/lib/toolchain/process.js.map +1 -0
  477. package/packages/tools/lib/toolchain/protocol.d.ts +122 -0
  478. package/packages/tools/lib/toolchain/protocol.d.ts.map +1 -0
  479. package/packages/tools/lib/toolchain/protocol.js +74 -0
  480. package/packages/tools/lib/toolchain/protocol.js.map +1 -0
  481. package/packages/tools/lib/toolchain/providers/internal-kpar.d.ts +9 -0
  482. package/packages/tools/lib/toolchain/providers/internal-kpar.d.ts.map +1 -0
  483. package/packages/tools/lib/toolchain/providers/internal-kpar.js +84 -0
  484. package/packages/tools/lib/toolchain/providers/internal-kpar.js.map +1 -0
  485. package/packages/tools/lib/toolchain/providers/internal.d.ts +33 -0
  486. package/packages/tools/lib/toolchain/providers/internal.d.ts.map +1 -0
  487. package/packages/tools/lib/toolchain/providers/internal.js +286 -0
  488. package/packages/tools/lib/toolchain/providers/internal.js.map +1 -0
  489. package/packages/tools/lib/toolchain/providers/sysand.d.ts +12 -0
  490. package/packages/tools/lib/toolchain/providers/sysand.d.ts.map +1 -0
  491. package/packages/tools/lib/toolchain/providers/sysand.js +110 -0
  492. package/packages/tools/lib/toolchain/providers/sysand.js.map +1 -0
  493. package/packages/tools/lib/toolchain/providers/syside.d.ts +24 -0
  494. package/packages/tools/lib/toolchain/providers/syside.d.ts.map +1 -0
  495. package/packages/tools/lib/toolchain/providers/syside.js +208 -0
  496. package/packages/tools/lib/toolchain/providers/syside.js.map +1 -0
  497. package/packages/tools/lib/toolchain/registry.d.ts +192 -0
  498. package/packages/tools/lib/toolchain/registry.d.ts.map +1 -0
  499. package/packages/tools/lib/toolchain/registry.js +130 -0
  500. package/packages/tools/lib/toolchain/registry.js.map +1 -0
  501. package/packages/tools/lib/toolchain/schema.d.ts +30 -0
  502. package/packages/tools/lib/toolchain/schema.d.ts.map +1 -0
  503. package/packages/tools/lib/toolchain/schema.js +112 -0
  504. package/packages/tools/lib/toolchain/schema.js.map +1 -0
  505. package/packages/tools/lib/toolchain/sysmlc-client.d.ts +77 -0
  506. package/packages/tools/lib/toolchain/sysmlc-client.d.ts.map +1 -0
  507. package/packages/tools/lib/toolchain/sysmlc-client.js +0 -0
  508. package/packages/tools/lib/toolchain/sysmlc-client.js.map +1 -0
  509. package/packages/tools/lib/validator/architecture-validator.d.ts +8 -1
  510. package/packages/tools/lib/validator/architecture-validator.d.ts.map +1 -1
  511. package/packages/tools/lib/validator/architecture-validator.js +25 -1
  512. package/packages/tools/lib/validator/architecture-validator.js.map +1 -1
  513. package/packages/tools/lib/validator/behavior-validator.d.ts +1 -1
  514. package/packages/tools/lib/validator/behavior-validator.js +1 -1
  515. package/packages/tools/lib/validator/builtin-rules.d.ts +16 -0
  516. package/packages/tools/lib/validator/builtin-rules.d.ts.map +1 -0
  517. package/packages/tools/lib/validator/builtin-rules.js +62 -0
  518. package/packages/tools/lib/validator/builtin-rules.js.map +1 -0
  519. package/packages/tools/lib/validator/constraint-eval.d.ts +31 -0
  520. package/packages/tools/lib/validator/constraint-eval.d.ts.map +1 -1
  521. package/packages/tools/lib/validator/constraint-eval.js +164 -7
  522. package/packages/tools/lib/validator/constraint-eval.js.map +1 -1
  523. package/packages/tools/lib/validator/constraint-loader.d.ts +22 -4
  524. package/packages/tools/lib/validator/constraint-loader.d.ts.map +1 -1
  525. package/packages/tools/lib/validator/constraint-loader.js +100 -27
  526. package/packages/tools/lib/validator/constraint-loader.js.map +1 -1
  527. package/packages/tools/lib/validator/rule-engine.d.ts +2 -1
  528. package/packages/tools/lib/validator/rule-engine.d.ts.map +1 -1
  529. package/packages/tools/lib/validator/rule-engine.js +56 -5
  530. package/packages/tools/lib/validator/rule-engine.js.map +1 -1
  531. package/packages/tools/lib/validator/sysml-constraints.d.ts +64 -0
  532. package/packages/tools/lib/validator/sysml-constraints.d.ts.map +1 -0
  533. package/packages/tools/lib/validator/sysml-constraints.js +251 -0
  534. package/packages/tools/lib/validator/sysml-constraints.js.map +1 -0
  535. package/packages/tools/lib/validator/types.d.ts +33 -0
  536. package/packages/tools/lib/validator/types.d.ts.map +1 -1
  537. package/packages/tools/lib/version.d.ts +2 -0
  538. package/packages/tools/lib/version.d.ts.map +1 -0
  539. package/packages/tools/lib/version.js +26 -0
  540. package/packages/tools/lib/version.js.map +1 -0
  541. package/packages/tools/src/grammar/memo-sysml.langium +517 -41
  542. package/packages/tools/lib/model/dimension-filter.d.ts +0 -33
  543. package/packages/tools/lib/model/dimension-filter.d.ts.map +0 -1
  544. package/packages/tools/lib/model/dimension-filter.js +0 -57
  545. package/packages/tools/lib/model/dimension-filter.js.map +0 -1
  546. package/packages/tools/lib/model/toolchain.d.ts +0 -12
  547. package/packages/tools/lib/model/toolchain.d.ts.map +0 -1
  548. package/packages/tools/lib/model/toolchain.js +0 -92
  549. package/packages/tools/lib/model/toolchain.js.map +0 -1
@@ -0,0 +1,946 @@
1
+ // ─── Project conversion ──────────────────────────────────────────────────────
2
+ //
3
+ // Restructure a pre-native project into the section 6.2 catalog layout.
4
+ //
5
+ // This module is the risky half of session 4: it is the only code in MEMO that
6
+ // rewrites a user's authored model in bulk. Everything here is therefore built
7
+ // around one rule — PLANNING NEVER TOUCHES THE DISK. `planConversion` reads,
8
+ // classifies, and returns a complete description of what would change;
9
+ // `applyConversion` is the only function that writes, and it refuses outright
10
+ // when the plan reports a collision. A conversion that cannot be described
11
+ // exactly is not performed at all.
12
+ //
13
+ // The three things the plan decides, in order, because each depends on the one
14
+ // before it:
15
+ //
16
+ // 1. where each file belongs (path classification)
17
+ // 2. what its package is then called (namespace mirroring)
18
+ // 3. which references have to follow (imports, `expose`, artifact URIs)
19
+ //
20
+ // Step 3 is why this is not a shell script. A package rename is not a textual
21
+ // event local to one file: every `import`, every `expose`, and every qualified
22
+ // reference anywhere in the project names the old package, including in files
23
+ // that do not themselves move.
24
+ //
25
+ // Design reference: sections 6.2, 6.3, 18.4 (half A, deliverable 1).
26
+ // ─────────────────────────────────────────────────────────────────────────────
27
+ import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
28
+ import { basename, dirname, join, relative, resolve, sep } from 'node:path';
29
+ import { findSysmlFiles, isIgnoredDirectory } from './sysml-files.js';
30
+ import { PROJECT_ENTRYPOINT } from './native-project.js';
31
+ // ─── Layout knowledge ─────────────────────────────────────────────────────────
32
+ const CATALOG_ROOT = join('model', 'catalog');
33
+ /**
34
+ * Filenames that name their directory rather than a sibling concept.
35
+ *
36
+ * `viewpoints/risk/viewpoint.sysml` is the risk viewpoint's own file, so its
37
+ * package is `…_viewpoints_risk`, not `…_viewpoints_risk_viewpoint`. Without
38
+ * this the namespace grows a redundant segment at every index file.
39
+ */
40
+ const INDEX_BASENAMES = new Set(['viewpoint', 'catalog', 'index']);
41
+ /**
42
+ * Semantic YAML the flip removed (session 3). The converter deletes these
43
+ * rather than leaving them beside a native project, because a settings file
44
+ * carrying a semantic field is now a hard rejection at load: leaving one in
45
+ * place would convert the project into one that refuses to open.
46
+ */
47
+ const LEGACY_SEMANTIC_SETTINGS = [
48
+ 'memo.config.yaml', 'memo.rules.yaml', 'memo.viewpoints.yaml', 'memo.rendering.yaml',
49
+ ];
50
+ /**
51
+ * Where views that declare no governing viewpoint are collected.
52
+ *
53
+ * ISO 42010 puts every view under a viewpoint, and a view that names none has a
54
+ * real gap in it. The conversion neither invents a viewpoint nor drops the view
55
+ * — it puts them somewhere obvious and says so.
56
+ */
57
+ const UNCLASSIFIED_VIEW_GROUP = 'unassigned';
58
+ /** Directories under the project root that hold vendored reusable packages. */
59
+ const VENDORED_REUSABLE_DIRS = new Set(['methodology', 'methodologies', 'extensions', 'profile', 'profiles']);
60
+ const PACKAGE_RE = /^\s*package\s+([A-Za-z_][A-Za-z0-9_]*)/m;
61
+ const VIEW_RE = /^\s*view\s+([A-Za-z_][A-Za-z0-9_]*)\s*:/gm;
62
+ /**
63
+ * A viewpoint usage, in either spelling.
64
+ *
65
+ * MEMO declares viewpoints as `part <name> : Viewpoint`, not with the SysML
66
+ * `viewpoint` keyword — `Viewpoint` is a MEMO part definition carrying the
67
+ * ISO 42010 framing attributes. Matching only the keyword form found nothing in
68
+ * the ontology, which silently sent every view to the name-derived fallback
69
+ * group instead of the directory its viewpoint actually lives in.
70
+ */
71
+ const VIEWPOINT_RE = /^\s*(?:(?:part\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*\w*Viewpoint\b)|(?:viewpoint\s+([A-Za-z_][A-Za-z0-9_]*)\s*[:{]))/gm;
72
+ const VIEWPOINT_DEF_RE = /viewpointDefinition\s*=\s*([A-Za-z_][A-Za-z0-9_]*)/;
73
+ const IMPORT_RE = /^\s*(?:public|private)?\s*import\s+([A-Za-z_][A-Za-z0-9_]*)/gm;
74
+ export function readSourceFacts(text) {
75
+ const facts = { viewUsages: [], viewpointUsages: [], imports: [], declaresOnlyImports: false };
76
+ facts.packageName = PACKAGE_RE.exec(text)?.[1];
77
+ for (const m of text.matchAll(VIEW_RE))
78
+ facts.viewUsages.push(m[1]);
79
+ for (const m of text.matchAll(VIEWPOINT_RE))
80
+ facts.viewpointUsages.push(m[1] ?? m[2]);
81
+ facts.viewpointDefinition = VIEWPOINT_DEF_RE.exec(text)?.[1];
82
+ for (const m of text.matchAll(IMPORT_RE))
83
+ facts.imports.push(m[1]);
84
+ facts.declaresOnlyImports = facts.packageName !== undefined && text
85
+ .split('\n')
86
+ .map(line => line.replace(/\/\/.*$/, '').trim())
87
+ .every(line => line === '' || line === '}' || line === '{' ||
88
+ /^package\s/.test(line) || /^(public|private)?\s*import\s/.test(line));
89
+ return facts;
90
+ }
91
+ // ─── Naming ───────────────────────────────────────────────────────────────────
92
+ function snake(name) {
93
+ return name
94
+ .replace(/([a-z0-9])([A-Z])/g, '$1_$2')
95
+ .replace(/[^A-Za-z0-9]+/g, '_')
96
+ .toLowerCase()
97
+ .replace(/^_+|_+$/g, '');
98
+ }
99
+ /**
100
+ * Longest `_`-separated prefix shared by every project package.
101
+ *
102
+ * Derived rather than configured, because the prefix is already a fact about
103
+ * the project's source: whatever the packages agree on is the project's
104
+ * namespace. Trailing structural segments are dropped so that a project whose
105
+ * packages are all called `x_model_catalog_*` yields `x`, not `x_model_catalog`
106
+ * — those segments describe where files sit, and the whole point of the
107
+ * conversion is that the directory tree carries that instead.
108
+ */
109
+ export function deriveProjectPrefix(packageNames, sharedDirSegments = []) {
110
+ const lists = packageNames.filter(Boolean).map(n => n.split('_'));
111
+ if (lists.length === 0)
112
+ return undefined;
113
+ let common = lists[0];
114
+ for (const parts of lists.slice(1)) {
115
+ let i = 0;
116
+ while (i < common.length && i < parts.length && common[i] === parts[i])
117
+ i++;
118
+ common = common.slice(0, i);
119
+ }
120
+ // Trailing segments that only restate the directory EVERY file already sits
121
+ // under are location, and the catalog tree carries location now.
122
+ // `sysml-diagram-samples` keeps every file in `model/samples/`, so every
123
+ // package shares `…_model_samples`; carrying that into the prefix would
124
+ // reproduce the old paths inside the new names.
125
+ //
126
+ // The suffix is matched exactly against the shared directory path rather
127
+ // than against a list of structural-sounding words, because those two are
128
+ // not the same question: `samples` appears twice in that project's prefix,
129
+ // once as part of its name and once as the directory, and only the second
130
+ // may go.
131
+ let tail = sharedDirSegments.length;
132
+ while (tail > 0) {
133
+ const suffix = sharedDirSegments.slice(sharedDirSegments.length - tail);
134
+ if (common.length > suffix.length &&
135
+ suffix.every((seg, i) => common[common.length - suffix.length + i] === seg)) {
136
+ common = common.slice(0, common.length - suffix.length);
137
+ break;
138
+ }
139
+ tail--;
140
+ }
141
+ while (common.length > 1 && ['model', 'catalog', 'src'].includes(common[common.length - 1])) {
142
+ common = common.slice(0, -1);
143
+ }
144
+ return common.length > 0 ? common.join('_') : undefined;
145
+ }
146
+ /**
147
+ * The directory path every project `.sysml` file sits under, as name segments.
148
+ *
149
+ * Empty for a project whose sources are spread across sibling directories,
150
+ * which is the common case and correctly leaves the prefix alone.
151
+ */
152
+ function sharedDirectorySegments(relPaths) {
153
+ if (relPaths.length === 0)
154
+ return [];
155
+ const dirs = relPaths.map(p => p.split(/[\\/]/).slice(0, -1));
156
+ let common = dirs[0];
157
+ for (const parts of dirs.slice(1)) {
158
+ let i = 0;
159
+ while (i < common.length && i < parts.length && common[i] === parts[i])
160
+ i++;
161
+ common = common.slice(0, i);
162
+ }
163
+ return common.flatMap(seg => snake(seg).split('_')).filter(Boolean);
164
+ }
165
+ /**
166
+ * The package name a file at `catalogRelPath` should declare.
167
+ *
168
+ * Namespace mirroring, mechanically: prefix, then the directory chain, then the
169
+ * basename — except where the basename only restates the directory it sits in.
170
+ */
171
+ export function derivePackageName(prefix, catalogRelPath) {
172
+ const segments = catalogRelPath.split(/[\\/]/).filter(Boolean);
173
+ const file = segments.pop().replace(/\.sysml$/, '');
174
+ const parent = segments[segments.length - 1];
175
+ const redundant = INDEX_BASENAMES.has(file) || (parent !== undefined && file === parent);
176
+ const parts = [prefix, ...segments, ...(redundant ? [] : [file])];
177
+ return parts.map(snake).filter(Boolean).join('_');
178
+ }
179
+ /**
180
+ * Whether an in-place file's declared package already mirrors its location.
181
+ *
182
+ * Two forms are accepted: the canonical one `derivePackageName` emits, and the
183
+ * same name with the trailing basename segment dropped. Both place the package
184
+ * at or under its directory's namespace, which is what mirroring means. The
185
+ * short form is accepted rather than "corrected" because rewriting a package
186
+ * name is a real edit to a user's model, and MEMO's own hand-authored catalog
187
+ * uses it — a converter that churned those files would fail its own
188
+ * idempotence test for a purely cosmetic reason.
189
+ */
190
+ export function isMirroringPackageName(name, prefix, catalogRelPath) {
191
+ const canonical = derivePackageName(prefix, catalogRelPath);
192
+ if (name === canonical)
193
+ return true;
194
+ const segments = catalogRelPath.split(/[\\/]/).filter(Boolean);
195
+ segments.pop();
196
+ const short = [prefix, ...segments].map(snake).filter(Boolean).join('_');
197
+ return name === short;
198
+ }
199
+ /**
200
+ * Where a source file belongs after conversion.
201
+ *
202
+ * The classification is structural — a file's current directory and the
203
+ * constructs it declares — and never guesses at ontology layer. Deciding that
204
+ * `gpca_risk.sysml` "is" safety/risk content would mean the converter forming
205
+ * an opinion about model semantics, and getting that wrong silently relocates a
206
+ * user's model into a namespace they did not choose. Files already inside the
207
+ * catalog therefore keep their place; only files outside it, whose location is
208
+ * unambiguously wrong under section 6.2, are moved.
209
+ */
210
+ export function classifyFile(relPath, facts, viewpointGroup) {
211
+ const norm = relPath.split(sep).join('/');
212
+ if (norm === CATALOG_ROOT.split(sep).join('/') + '/project.sysml') {
213
+ return { role: 'entrypoint', to: relPath };
214
+ }
215
+ const top = norm.split('/')[0];
216
+ if (VENDORED_REUSABLE_DIRS.has(top))
217
+ return { role: 'vendored-reusable', to: relPath };
218
+ // A re-export wrapper sitting directly under `model/` is the pre-catalog
219
+ // way of giving a project one public package to import. `project.sysml` is
220
+ // that entrypoint now, so the wrapper is superseded rather than relocated —
221
+ // moving it would put a second entrypoint inside the catalog, and every
222
+ // shipped example carried one.
223
+ if (facts.declaresOnlyImports && /^model\/[^/]+\.sysml$/.test(norm)) {
224
+ return { role: 'legacy-entrypoint', to: relPath };
225
+ }
226
+ const isViewFile = facts.viewUsages.length > 0;
227
+ const isViewpointFile = !isViewFile && facts.viewpointUsages.length > 0;
228
+ const inViewsDir = /(^|\/)(views|viewpoints)\//.test(norm);
229
+ if (isViewFile) {
230
+ // A view's viewpoint is a declared fact in the file, and it is a better
231
+ // grouping than the filename: GPCA's `behavior_action_flow_view.sysml`
232
+ // is governed by the logical viewpoint, and `document_*` views spread
233
+ // across six different viewpoints. Filename prefixes would have put all
234
+ // of them in the wrong place.
235
+ // A view that names no governing viewpoint cannot be filed against
236
+ // one. Deriving a group from its filename would invent an ISO 42010
237
+ // viewpoint the model never declared, so these collect under one
238
+ // clearly-named group and are reported for an author to place.
239
+ const group = facts.viewpointDefinition
240
+ ? viewpointGroup(facts.viewpointDefinition)
241
+ : UNCLASSIFIED_VIEW_GROUP;
242
+ return { role: 'view', to: join(CATALOG_ROOT, 'viewpoints', group, 'views', basename(norm)) };
243
+ }
244
+ if (isViewpointFile || (inViewsDir && facts.viewpointUsages.length > 0)) {
245
+ const group = facts.viewpointUsages.length > 0
246
+ ? viewpointGroup(facts.viewpointUsages[0])
247
+ : UNCLASSIFIED_VIEW_GROUP;
248
+ return { role: 'viewpoint', to: join(CATALOG_ROOT, 'viewpoints', group, 'viewpoint.sysml') };
249
+ }
250
+ if (norm.startsWith('model/catalog/'))
251
+ return { role: 'catalog', to: relPath };
252
+ if (norm.startsWith('model/')) {
253
+ return { role: 'catalog', to: join(CATALOG_ROOT, norm.slice('model/'.length)) };
254
+ }
255
+ return { role: 'catalog', to: join(CATALOG_ROOT, norm) };
256
+ }
257
+ /**
258
+ * Directory name for the viewpoint a view is governed by.
259
+ *
260
+ * Prefers the directory the reusable viewpoint's own source sits in, so a
261
+ * project's `viewpoints/risk/` lines up with the ontology's
262
+ * `src/viewpoints/risk/`. Falls back to the usage name with its `Viewpoint`
263
+ * suffix removed.
264
+ */
265
+ export function viewpointGroupName(usageName, declaringFileByUsage) {
266
+ const declaring = declaringFileByUsage.get(usageName);
267
+ if (declaring) {
268
+ const dir = basename(dirname(declaring));
269
+ if (dir && dir !== 'viewpoints' && dir !== 'src')
270
+ return snake(dir);
271
+ }
272
+ return snake(usageName.replace(/Viewpoint$/, ''));
273
+ }
274
+ // ─── Reference rewriting ──────────────────────────────────────────────────────
275
+ /**
276
+ * Rewrite package references in `text` according to `renames`.
277
+ *
278
+ * Word-boundary anchored and applied longest-name-first, because package names
279
+ * nest: renaming `a_b` before `a_b_c` would corrupt every reference to the
280
+ * longer name. Comments and doc strings are rewritten too — deliberately, since
281
+ * a stale package name in a comment is a documentation defect the conversion
282
+ * would otherwise create.
283
+ */
284
+ export function rewritePackageReferences(text, renames) {
285
+ const ordered = [...renames.entries()].sort((a, b) => b[0].length - a[0].length);
286
+ let out = text;
287
+ for (const [from, to] of ordered) {
288
+ if (from === to)
289
+ continue;
290
+ out = out.replace(new RegExp(`\\b${escapeRe(from)}\\b`, 'g'), to);
291
+ }
292
+ return out;
293
+ }
294
+ /**
295
+ * Rewrite the file's own `package <name>` declaration.
296
+ *
297
+ * Separate from reference rewriting because a file's declaration is renamed
298
+ * even when nothing else refers to it, and because the declaration is the one
299
+ * occurrence that must change exactly once.
300
+ */
301
+ export function rewritePackageDeclaration(text, toPackage) {
302
+ return text.replace(/^(\s*package\s+)([A-Za-z_][A-Za-z0-9_]*)/m, `$1${toPackage}`);
303
+ }
304
+ /**
305
+ * Rewrite model-owned payload URIs to follow their payload files.
306
+ *
307
+ * Artifact identities carry a project-relative URI (`imageUri`, `uri`,
308
+ * `payloadUri`, `sourceUri`). When the payload moves, an unrewritten URI leaves
309
+ * the artifact pointing at nothing, and the hash check that would have caught
310
+ * it passes vacuously because the file is simply absent. This is the quietest
311
+ * failure the conversion could produce, so it is handled explicitly rather than
312
+ * left to the package-reference pass.
313
+ */
314
+ export function rewriteArtifactUris(text, moves) {
315
+ const ordered = [...moves.entries()].sort((a, b) => b[0].length - a[0].length);
316
+ let out = text;
317
+ for (const [from, to] of ordered) {
318
+ if (from === to)
319
+ continue;
320
+ const fromPosix = from.split(sep).join('/');
321
+ const toPosix = to.split(sep).join('/');
322
+ out = out.replace(new RegExp(`"${escapeRe(fromPosix)}"`, 'g'), `"${toPosix}"`);
323
+ // Also match a URI written relative to `model/`, which is how
324
+ // pre-catalog projects addressed their own payloads.
325
+ const fromShort = fromPosix.replace(/^model\//, '');
326
+ const toShort = toPosix.replace(/^model\//, '');
327
+ if (fromShort !== fromPosix) {
328
+ out = out.replace(new RegExp(`"${escapeRe(fromShort)}"`, 'g'), `"${toShort}"`);
329
+ }
330
+ }
331
+ return out;
332
+ }
333
+ function escapeRe(s) {
334
+ return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
335
+ }
336
+ function push(map, key, value) {
337
+ const list = map.get(key);
338
+ if (list)
339
+ list.push(value);
340
+ else
341
+ map.set(key, [value]);
342
+ }
343
+ // ─── Payload discovery ────────────────────────────────────────────────────────
344
+ /** Non-SysML files under `model/` that are model-owned artifact payloads. */
345
+ function findPayloadFiles(projectRoot) {
346
+ const modelDir = join(projectRoot, 'model');
347
+ if (!existsSync(modelDir))
348
+ return [];
349
+ const out = [];
350
+ const walk = (dir) => {
351
+ let entries;
352
+ try {
353
+ entries = readdirSync(dir, { withFileTypes: true });
354
+ }
355
+ catch {
356
+ return;
357
+ }
358
+ for (const entry of entries) {
359
+ const full = join(dir, entry.name);
360
+ if (entry.isDirectory()) {
361
+ if (!isIgnoredDirectory(entry.name))
362
+ walk(full);
363
+ }
364
+ else if (!entry.name.endsWith('.sysml')) {
365
+ out.push(full);
366
+ }
367
+ }
368
+ };
369
+ walk(modelDir);
370
+ return out;
371
+ }
372
+ /** Where a payload file belongs: alongside the assets catalog. */
373
+ function payloadTarget(relPath) {
374
+ const norm = relPath.split(sep).join('/');
375
+ if (norm.startsWith('model/catalog/artifacts/'))
376
+ return relPath;
377
+ if (norm.startsWith('model/assets/')) {
378
+ return join(CATALOG_ROOT, 'artifacts', 'assets', norm.slice('model/assets/'.length));
379
+ }
380
+ if (norm.startsWith('model/catalog/'))
381
+ return relPath;
382
+ return join(CATALOG_ROOT, norm.slice('model/'.length));
383
+ }
384
+ /**
385
+ * Describe, without writing anything, the conversion of `projectRoot`.
386
+ *
387
+ * Every disk write in this module happens in `applyConversion`. That split is
388
+ * what makes `--dry-run` trustworthy: dry-run is not a flag threaded through
389
+ * the write path that might be missed on one branch, it is the absence of a
390
+ * call to the only function that writes.
391
+ */
392
+ export function planConversion(projectRoot, options = {}) {
393
+ const root = resolve(projectRoot);
394
+ const collisions = [];
395
+ const warnings = [];
396
+ const sysmlFiles = findSysmlFiles(root).sort();
397
+ const rel = (f) => relative(root, f);
398
+ // 1. Read every file once.
399
+ const facts = new Map();
400
+ const text = new Map();
401
+ for (const file of sysmlFiles) {
402
+ let content;
403
+ try {
404
+ content = readFileSync(file, 'utf-8');
405
+ }
406
+ catch {
407
+ continue;
408
+ }
409
+ text.set(rel(file), content);
410
+ facts.set(rel(file), readSourceFacts(content));
411
+ }
412
+ // 2. The project's namespace prefix.
413
+ const projectPackages = [...facts.entries()]
414
+ .filter(([relPath]) => !VENDORED_REUSABLE_DIRS.has(relPath.split(sep)[0]))
415
+ .map(([, f]) => f.packageName)
416
+ .filter((n) => Boolean(n));
417
+ const projectPrefix = deriveProjectPrefix(projectPackages, sharedDirectorySegments([...facts.keys()]));
418
+ if (!projectPrefix) {
419
+ collisions.push({
420
+ code: 'no-project-prefix',
421
+ message: 'No project package prefix could be derived: no .sysml file declares a package.',
422
+ files: [],
423
+ });
424
+ return emptyPlan(root, '', collisions, warnings);
425
+ }
426
+ // 3. Viewpoint grouping, from the reusable closure when the caller resolved
427
+ // one and from the project's own declarations otherwise.
428
+ const declaringFileByUsage = new Map(options.viewpointDeclarations ?? []);
429
+ for (const [relPath, f] of facts) {
430
+ for (const vp of f.viewpointUsages) {
431
+ if (!declaringFileByUsage.has(vp))
432
+ declaringFileByUsage.set(vp, relPath);
433
+ }
434
+ }
435
+ const groupOf = (usage) => viewpointGroupName(usage, declaringFileByUsage);
436
+ // 4. Classify, and derive the target package for anything that moves.
437
+ const changes = [];
438
+ const packageRenames = new Map();
439
+ const destinations = new Map();
440
+ const viewpointGroupsSeen = new Map(); // group → source viewpoint usage
441
+ const supersededEntrypoints = [];
442
+ for (const [relPath, f] of [...facts.entries()].sort()) {
443
+ const { role, to } = classifyFile(relPath, f, groupOf);
444
+ if (role === 'legacy-entrypoint') {
445
+ // Only superseded if nothing else names it. A wrapper another file
446
+ // imports is load-bearing, and deleting it would break that import
447
+ // — so the plan refuses rather than removing it.
448
+ const referrers = [...facts.entries()]
449
+ .filter(([other, of_]) => other !== relPath && f.packageName
450
+ && (of_.imports.includes(f.packageName)))
451
+ .map(([other]) => other);
452
+ if (referrers.length > 0) {
453
+ collisions.push({
454
+ code: 'referenced-superseded-entrypoint',
455
+ message: `${relPath} is a re-export wrapper superseded by model/catalog/project.sysml, ` +
456
+ `but ${referrers.length} file(s) import ${f.packageName}. Repoint them at the ` +
457
+ 'packages they actually need, then convert.',
458
+ files: [relPath, ...referrers],
459
+ });
460
+ continue;
461
+ }
462
+ supersededEntrypoints.push(relPath);
463
+ warnings.push({
464
+ code: 'superseded-entrypoint',
465
+ file: relPath,
466
+ message: `${relPath} is removed: it is a re-export wrapper that gave the project one public ` +
467
+ 'package to import, which is model/catalog/project.sysml\'s job now. Nothing imports it.',
468
+ });
469
+ continue;
470
+ }
471
+ if (role === 'vendored-reusable') {
472
+ warnings.push({
473
+ code: 'vendored-reusable-package',
474
+ file: relPath,
475
+ message: `${relPath} is a project-vendored reusable package, not project catalog content. ` +
476
+ 'It is left in place: relocating it into model/catalog/ would assert that the ' +
477
+ 'methodology or extension it declares is project-owned, which is a semantic claim ' +
478
+ 'the conversion is not entitled to make.',
479
+ });
480
+ continue;
481
+ }
482
+ push(destinations, to, relPath);
483
+ const catalogRel = to.split(sep).join('/').replace(/^model\/catalog\//, '');
484
+ const moved = to !== relPath;
485
+ const reasons = [];
486
+ if (moved)
487
+ reasons.push(`relocated to the section 6.2 catalog layout (${role})`);
488
+ let toPackage = f.packageName;
489
+ if (f.packageName) {
490
+ if (moved) {
491
+ toPackage = derivePackageName(projectPrefix, catalogRel);
492
+ if (toPackage !== f.packageName) {
493
+ reasons.push('package renamed to mirror its new namespace');
494
+ packageRenames.set(f.packageName, toPackage);
495
+ }
496
+ }
497
+ else if (role === 'entrypoint'
498
+ && [projectPrefix, `${projectPrefix}_project`, `${projectPrefix}_catalog`]
499
+ .includes(f.packageName)) {
500
+ // The entrypoint's package IS the project's namespace root, and
501
+ // it has several equally correct spellings. Rewriting one to
502
+ // another would rename the package every import in the project
503
+ // resolves through, to no end.
504
+ }
505
+ else if (!isMirroringPackageName(f.packageName, projectPrefix, catalogRel)) {
506
+ const canonical = derivePackageName(projectPrefix, catalogRel);
507
+ if (options.normalizeNames) {
508
+ toPackage = canonical;
509
+ reasons.push('package renamed to mirror its location');
510
+ packageRenames.set(f.packageName, canonical);
511
+ }
512
+ else {
513
+ warnings.push({
514
+ code: 'package-not-mirroring',
515
+ file: relPath,
516
+ message: `${relPath} declares ${f.packageName}, which does not mirror its location ` +
517
+ `(expected ${canonical}). The file is not moving, so its declaration is left ` +
518
+ 'alone; re-run with --normalize-names to rename it.',
519
+ });
520
+ }
521
+ }
522
+ }
523
+ else {
524
+ collisions.push({
525
+ code: 'unparsed-package',
526
+ message: `${relPath} declares no SysML package, so its namespace cannot be placed.`,
527
+ files: [relPath],
528
+ });
529
+ }
530
+ if (role === 'view' && !facts.get(relPath)?.viewpointDefinition) {
531
+ warnings.push({
532
+ code: 'unclassified-view',
533
+ file: relPath,
534
+ message: `${relPath} declares a view but no governing viewpoint, so it lands under ` +
535
+ `viewpoints/${UNCLASSIFIED_VIEW_GROUP}/. Give it a viewpointDefinition and move it ` +
536
+ 'to that viewpoint — ISO 42010 puts every view under one.',
537
+ });
538
+ }
539
+ if (role === 'view' || role === 'viewpoint') {
540
+ // model/catalog/viewpoints/<group>/…
541
+ const group = to.split(sep)[3];
542
+ if (group && !viewpointGroupsSeen.has(group)) {
543
+ viewpointGroupsSeen.set(group, f.viewpointDefinition ?? f.viewpointUsages[0] ?? group);
544
+ }
545
+ }
546
+ if (reasons.length > 0 || moved) {
547
+ changes.push({ from: relPath, to, fromPackage: f.packageName, toPackage, reasons });
548
+ }
549
+ }
550
+ // 5. Payload files follow their artifact identities.
551
+ const payloadMoves = new Map();
552
+ for (const file of findPayloadFiles(root)) {
553
+ const from = rel(file);
554
+ const to = payloadTarget(from);
555
+ if (to === from)
556
+ continue;
557
+ payloadMoves.set(from, to);
558
+ push(destinations, to, from);
559
+ changes.push({ from, to, reasons: ['artifact payload follows its identity into artifacts/assets/'] });
560
+ }
561
+ // 6. Collisions: two sources landing on one destination, two packages
562
+ // taking one name, or a destination that already holds a different file.
563
+ for (const [to, sources] of destinations) {
564
+ if (sources.length > 1) {
565
+ collisions.push({
566
+ code: 'destination-conflict',
567
+ message: `${sources.length} files would be written to ${to}. The conversion refuses rather ` +
568
+ 'than picking a winner or writing a suffixed duplicate; rename one of them first.',
569
+ files: sources,
570
+ });
571
+ }
572
+ }
573
+ const byNewName = new Map();
574
+ for (const change of changes) {
575
+ if (!change.toPackage)
576
+ continue;
577
+ push(byNewName, change.toPackage, change.from);
578
+ }
579
+ for (const [name, sources] of byNewName) {
580
+ const others = [...facts.entries()]
581
+ .filter(([relPath, f]) => f.packageName === name && !sources.includes(relPath)
582
+ && !changes.some(c => c.from === relPath))
583
+ .map(([relPath]) => relPath);
584
+ if (sources.length + others.length > 1) {
585
+ collisions.push({
586
+ code: 'package-name-conflict',
587
+ message: `Package ${name} would be declared by ${sources.length + others.length} files. ` +
588
+ 'Section 18.6 rejects overloaded names rather than ranking them.',
589
+ files: [...sources, ...others],
590
+ });
591
+ }
592
+ }
593
+ for (const change of changes) {
594
+ if (change.to === change.from)
595
+ continue;
596
+ const dest = join(root, change.to);
597
+ if (existsSync(dest) && !changes.some(c => c.from === change.to)) {
598
+ collisions.push({
599
+ code: 'destination-occupied',
600
+ message: `${change.to} already exists and is not itself being moved.`,
601
+ files: [change.from, change.to],
602
+ });
603
+ }
604
+ }
605
+ // 7. Apply the rewrites to every file's text — including files that do not
606
+ // move, because a rename is a project-wide reference event.
607
+ const allRewrites = new Map(packageRenames);
608
+ for (const [relPath, content] of text) {
609
+ if (supersededEntrypoints.includes(relPath))
610
+ continue;
611
+ const change = changes.find(c => c.from === relPath);
612
+ let out = content;
613
+ if (change?.toPackage && change.toPackage !== change.fromPackage) {
614
+ out = rewritePackageDeclaration(out, change.toPackage);
615
+ }
616
+ out = rewritePackageReferences(out, allRewrites);
617
+ out = rewriteArtifactUris(out, payloadMoves);
618
+ if (out === content && !change)
619
+ continue;
620
+ if (change) {
621
+ change.content = out;
622
+ if (out !== content && !change.reasons.some(r => r.includes('reference'))) {
623
+ change.reasons.push('references to renamed packages rewritten');
624
+ }
625
+ }
626
+ else {
627
+ changes.push({
628
+ from: relPath, to: relPath,
629
+ fromPackage: facts.get(relPath)?.packageName,
630
+ toPackage: facts.get(relPath)?.packageName,
631
+ content: out,
632
+ reasons: ['references to renamed packages rewritten'],
633
+ });
634
+ }
635
+ }
636
+ // 8. Files the conversion creates: viewpoint bindings for groups that
637
+ // gained views but have no viewpoint file, and the entrypoint.
638
+ const newFiles = [];
639
+ const existingViewpointFiles = new Set(changes.filter(c => c.to.includes(`${sep}viewpoints${sep}`) && c.to.endsWith('viewpoint.sysml'))
640
+ .map(c => c.to));
641
+ for (const [group, usage] of viewpointGroupsSeen) {
642
+ const path = join(CATALOG_ROOT, 'viewpoints', group, 'viewpoint.sysml');
643
+ if (existingViewpointFiles.has(path) || existsSync(join(root, path)))
644
+ continue;
645
+ const declaringPackage = options.viewpointPackages?.get(usage);
646
+ newFiles.push({
647
+ path,
648
+ reason: `viewpoint binding for the ${group} views (ISO 42010: views sit beneath their viewpoint)`,
649
+ content: renderViewpointBinding(projectPrefix, group, usage, declaringPackage),
650
+ });
651
+ }
652
+ // 9. The entrypoint, when the project has none.
653
+ const entrypoint = PROJECT_ENTRYPOINT;
654
+ const hasEntrypoint = existsSync(join(root, entrypoint)) || changes.some(c => c.to === entrypoint);
655
+ const finalPackages = collectFinalPackages(facts, changes, newFiles, supersededEntrypoints);
656
+ if (!hasEntrypoint) {
657
+ newFiles.push({
658
+ path: entrypoint,
659
+ reason: 'native entrypoint: project identity, imports, and method binding',
660
+ content: renderEntrypoint(projectPrefix, root, finalPackages),
661
+ });
662
+ }
663
+ // 10. Legacy semantic settings and superseded wrappers are consumed, not
664
+ // left beside the result.
665
+ const removals = [...supersededEntrypoints];
666
+ for (const name of LEGACY_SEMANTIC_SETTINGS) {
667
+ if (!existsSync(join(root, name)))
668
+ continue;
669
+ removals.push(name);
670
+ warnings.push({
671
+ code: 'legacy-settings-file',
672
+ file: name,
673
+ message: `${name} is removed: it carries semantic fields that no longer participate in the ` +
674
+ 'model, and settings-boundary rejects them at load. Its selection is expressed by the ' +
675
+ 'entrypoint binding instead.',
676
+ });
677
+ }
678
+ const alreadyConverted = changes.every(c => c.from === c.to && c.content === undefined) &&
679
+ newFiles.length === 0 && removals.length === 0;
680
+ return {
681
+ projectRoot: root,
682
+ projectPrefix,
683
+ alreadyConverted,
684
+ changes: changes.sort((a, b) => a.from.localeCompare(b.from)),
685
+ newFiles,
686
+ removals,
687
+ packageRenames,
688
+ collisions,
689
+ warnings,
690
+ };
691
+ }
692
+ function emptyPlan(root, prefix, collisions, warnings) {
693
+ return {
694
+ projectRoot: root, projectPrefix: prefix, alreadyConverted: false,
695
+ changes: [], newFiles: [], removals: [], packageRenames: new Map(), collisions, warnings,
696
+ };
697
+ }
698
+ function collectFinalPackages(facts, changes, newFiles, removed) {
699
+ const names = new Set();
700
+ for (const [relPath, f] of facts) {
701
+ if (removed.includes(relPath))
702
+ continue;
703
+ const change = changes.find(c => c.from === relPath);
704
+ const name = change?.toPackage ?? f.packageName;
705
+ if (name)
706
+ names.add(name);
707
+ }
708
+ for (const f of newFiles) {
709
+ const name = readSourceFacts(f.content).packageName;
710
+ if (name)
711
+ names.add(name);
712
+ }
713
+ return [...names].sort();
714
+ }
715
+ // ─── Rendering ────────────────────────────────────────────────────────────────
716
+ function renderViewpointBinding(prefix, group, usage, declaringPackage) {
717
+ const pkg = derivePackageName(prefix, `viewpoints/${group}/viewpoint.sysml`);
718
+ const importLine = declaringPackage
719
+ ? ` public import ${declaringPackage}::*;`
720
+ : ` // The reusable package declaring ${usage} could not be resolved during\n` +
721
+ ` // conversion. Import it here so the views beneath this viewpoint resolve.`;
722
+ return [
723
+ `// ${group} viewpoint.`,
724
+ '//',
725
+ '// This project does not define its own viewpoint here; it binds the reusable',
726
+ '// MEMO viewpoint that frames these concerns. The views it governs sit beneath',
727
+ '// `views/`.',
728
+ `package ${pkg} {`,
729
+ importLine,
730
+ '}',
731
+ '',
732
+ ].join('\n');
733
+ }
734
+ /**
735
+ * The entrypoint a converted project gets when it had none.
736
+ *
737
+ * The binding is written with a placeholder methodology reference rather than a
738
+ * guess. A conversion cannot know which methodology a legacy project intended —
739
+ * `memo.config.yaml: methodology` held a package spec, not a usage name, and
740
+ * resolving one to the other requires the methodology package to be present.
741
+ * Emitting a name that does not resolve produces a source diagnostic the user
742
+ * sees immediately, which is the correct failure: loud, local, and one edit
743
+ * away from correct.
744
+ */
745
+ function renderEntrypoint(prefix, root, packages) {
746
+ const pkg = `${prefix}_project`;
747
+ const projectName = basename(root)
748
+ .split(/[-_]/).map(s => s.charAt(0).toUpperCase() + s.slice(1)).join(' ');
749
+ const idBase = prefix.split('_').slice(-2).join('-').toUpperCase();
750
+ const own = packages.filter(p => p.startsWith(`${prefix}_`) && p !== pkg);
751
+ return [
752
+ `// ${projectName} — project identity and method binding.`,
753
+ '//',
754
+ '// The native entrypoint. The imports name what this project contains and the',
755
+ '// binding names the methodology it is governed by. No YAML file participates.',
756
+ `package ${pkg} {`,
757
+ ' private import ScalarValues::*;',
758
+ '',
759
+ ' private import memo_core_enumerations::*;',
760
+ ' private import memo_methodology_core::*;',
761
+ ' private import memo_methodology_profiles::*;',
762
+ '',
763
+ ' // The project\'s own content, imported so the catalog is one reachable',
764
+ ' // closure from a single entrypoint.',
765
+ ...own.map(p => ` private import ${p}::*;`),
766
+ '',
767
+ ` part projectBinding : ProjectMethodBinding {`,
768
+ ` attribute :>> id = "PMB-${idBase}-001";`,
769
+ ` attribute :>> name = "${projectName.replace(/\s+/g, '')}ProjectMethodBinding";`,
770
+ ` attribute :>> projectName = "${projectName}";`,
771
+ ' ref :>> selectedMethodology = mdDefaultDefinition;',
772
+ ' attribute :>> scopeMode = ScopeModeKind::explicit;',
773
+ ' }',
774
+ '}',
775
+ '',
776
+ ].join('\n');
777
+ }
778
+ // ─── Diff rendering ───────────────────────────────────────────────────────────
779
+ /**
780
+ * A human-readable description of the plan.
781
+ *
782
+ * Deliberately not a unified content diff by default: the conversion's changes
783
+ * are overwhelmingly moves and one-token renames, and a line-level diff of
784
+ * twenty relocated files buries the two facts a reviewer needs — what moved,
785
+ * and what got renamed. `--diff` adds the content hunks on top of this.
786
+ */
787
+ export function renderPlan(plan, options = {}) {
788
+ const out = [];
789
+ const rel = plan.projectRoot;
790
+ if (plan.collisions.length > 0) {
791
+ out.push('REFUSED — the conversion cannot be described unambiguously:', '');
792
+ for (const c of plan.collisions) {
793
+ out.push(` [${c.code}] ${c.message}`);
794
+ for (const f of c.files)
795
+ out.push(` ${f}`);
796
+ out.push('');
797
+ }
798
+ return out.join('\n');
799
+ }
800
+ if (plan.alreadyConverted) {
801
+ return `${rel}\n Already in the native catalog layout. Nothing to convert.\n`;
802
+ }
803
+ out.push(`${rel}`, ` project namespace: ${plan.projectPrefix}`, '');
804
+ const moves = plan.changes.filter(c => c.from !== c.to);
805
+ const inPlace = plan.changes.filter(c => c.from === c.to && c.content !== undefined);
806
+ if (moves.length > 0) {
807
+ out.push(` Moves (${moves.length}):`);
808
+ for (const c of moves) {
809
+ out.push(` ${c.from}`);
810
+ out.push(` → ${c.to}`);
811
+ if (c.fromPackage && c.toPackage && c.fromPackage !== c.toPackage) {
812
+ out.push(` package ${c.fromPackage} → ${c.toPackage}`);
813
+ }
814
+ }
815
+ out.push('');
816
+ }
817
+ if (inPlace.length > 0) {
818
+ out.push(` Rewritten in place (${inPlace.length}):`);
819
+ for (const c of inPlace)
820
+ out.push(` ${c.from} — ${c.reasons.join('; ')}`);
821
+ out.push('');
822
+ }
823
+ if (plan.newFiles.length > 0) {
824
+ out.push(` Created (${plan.newFiles.length}):`);
825
+ for (const f of plan.newFiles)
826
+ out.push(` ${f.path} — ${f.reason}`);
827
+ out.push('');
828
+ }
829
+ if (plan.removals.length > 0) {
830
+ out.push(` Removed (${plan.removals.length}):`);
831
+ for (const f of plan.removals)
832
+ out.push(` ${f}`);
833
+ out.push('');
834
+ }
835
+ if (plan.warnings.length > 0) {
836
+ out.push(` Warnings (${plan.warnings.length}):`);
837
+ for (const w of plan.warnings)
838
+ out.push(` [${w.code}] ${w.message}`);
839
+ out.push('');
840
+ }
841
+ if (options.diff) {
842
+ for (const c of plan.changes) {
843
+ if (c.content === undefined)
844
+ continue;
845
+ let before;
846
+ try {
847
+ before = readFileSync(join(plan.projectRoot, c.from), 'utf-8');
848
+ }
849
+ catch {
850
+ continue;
851
+ }
852
+ const hunks = lineDiff(before, c.content);
853
+ if (hunks.length === 0)
854
+ continue;
855
+ out.push(`--- a/${c.from}`, `+++ b/${c.to}`, ...hunks, '');
856
+ }
857
+ for (const f of plan.newFiles) {
858
+ out.push(`--- /dev/null`, `+++ b/${f.path}`, ...f.content.split('\n').map(l => `+${l}`), '');
859
+ }
860
+ }
861
+ return out.join('\n');
862
+ }
863
+ /** Changed lines with one line of context. Enough to review a rename. */
864
+ function lineDiff(before, after) {
865
+ const a = before.split('\n');
866
+ const b = after.split('\n');
867
+ const out = [];
868
+ for (let i = 0; i < Math.max(a.length, b.length); i++) {
869
+ if (a[i] === b[i])
870
+ continue;
871
+ if (a[i] !== undefined)
872
+ out.push(`-${a[i]}`);
873
+ if (b[i] !== undefined)
874
+ out.push(`+${b[i]}`);
875
+ }
876
+ return out;
877
+ }
878
+ /**
879
+ * The only function in this module that writes.
880
+ *
881
+ * It refuses a plan carrying collisions, and it refuses to duplicate: a move
882
+ * writes the destination and removes the source, so a half-applied conversion
883
+ * leaves one copy of each file rather than two divergent ones. Directories left
884
+ * empty by the moves are pruned, because an empty `model/views/` beside
885
+ * `model/catalog/viewpoints/` is exactly the superseded layout the conversion
886
+ * exists to eliminate.
887
+ */
888
+ export function applyConversion(plan) {
889
+ if (plan.collisions.length > 0) {
890
+ throw new Error(`Refusing to convert ${plan.projectRoot}: ${plan.collisions.length} collision(s). ` +
891
+ plan.collisions.map(c => c.message).join(' '));
892
+ }
893
+ const result = { written: [], moved: [], created: [], removed: [] };
894
+ const root = plan.projectRoot;
895
+ for (const change of plan.changes) {
896
+ const src = join(root, change.from);
897
+ const dest = join(root, change.to);
898
+ mkdirSync(dirname(dest), { recursive: true });
899
+ if (change.content !== undefined) {
900
+ writeFileSync(dest, change.content);
901
+ }
902
+ else if (src !== dest) {
903
+ writeFileSync(dest, readFileSync(src));
904
+ }
905
+ if (src !== dest) {
906
+ rmSync(src, { force: true });
907
+ result.moved.push(`${change.from} → ${change.to}`);
908
+ }
909
+ else if (change.content !== undefined) {
910
+ result.written.push(change.to);
911
+ }
912
+ }
913
+ for (const file of plan.newFiles) {
914
+ const dest = join(root, file.path);
915
+ mkdirSync(dirname(dest), { recursive: true });
916
+ writeFileSync(dest, file.content);
917
+ result.created.push(file.path);
918
+ }
919
+ for (const name of plan.removals) {
920
+ rmSync(join(root, name), { force: true });
921
+ result.removed.push(name);
922
+ }
923
+ pruneEmptyDirs(join(root, 'model'));
924
+ return result;
925
+ }
926
+ function pruneEmptyDirs(dir) {
927
+ if (!existsSync(dir))
928
+ return;
929
+ let entries;
930
+ try {
931
+ entries = readdirSync(dir, { withFileTypes: true });
932
+ }
933
+ catch {
934
+ return;
935
+ }
936
+ for (const entry of entries) {
937
+ if (entry.isDirectory())
938
+ pruneEmptyDirs(join(dir, entry.name));
939
+ }
940
+ try {
941
+ if (readdirSync(dir).length === 0 && basename(dir) !== 'model')
942
+ rmSync(dir, { recursive: true });
943
+ }
944
+ catch { /* raced or unreadable */ }
945
+ }
946
+ //# sourceMappingURL=project-conversion.js.map