@hydranium/cli 1.0.0-next.42 → 1.0.0-next.421

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 (371) hide show
  1. package/README.md +125 -204
  2. package/bin/hydranium-cli.js +13 -0
  3. package/heap-analysis/heap/core/load.mjs +2 -2
  4. package/heap-analysis/heap/langium/langium.classifier.mjs +22 -11
  5. package/lib/cli-version.js.map +1 -1
  6. package/lib/cli.js +11 -2
  7. package/lib/cli.js.map +1 -1
  8. package/lib/commands/analyze-heap-args.d.ts.map +1 -1
  9. package/lib/commands/analyze-heap-args.js +1 -2
  10. package/lib/commands/analyze-heap-args.js.map +1 -1
  11. package/lib/commands/analyze-heap.d.ts +3 -0
  12. package/lib/commands/analyze-heap.d.ts.map +1 -1
  13. package/lib/commands/analyze-heap.js +2 -1
  14. package/lib/commands/analyze-heap.js.map +1 -1
  15. package/lib/commands/ast-ground-truth-args.d.ts +3 -2
  16. package/lib/commands/ast-ground-truth-args.d.ts.map +1 -1
  17. package/lib/commands/ast-ground-truth-args.js +12 -10
  18. package/lib/commands/ast-ground-truth-args.js.map +1 -1
  19. package/lib/commands/ast-ground-truth-driver.js +4 -2
  20. package/lib/commands/ast-ground-truth-driver.js.map +1 -1
  21. package/lib/commands/ast-ground-truth.js +1 -1
  22. package/lib/commands/ast-ground-truth.js.map +1 -1
  23. package/lib/commands/check-skills-args.d.ts +11 -0
  24. package/lib/commands/check-skills-args.d.ts.map +1 -0
  25. package/lib/commands/check-skills-args.js +71 -0
  26. package/lib/commands/check-skills-args.js.map +1 -0
  27. package/lib/commands/client-session.d.ts +17 -0
  28. package/lib/commands/client-session.d.ts.map +1 -0
  29. package/lib/commands/client-session.js +27 -0
  30. package/lib/commands/client-session.js.map +1 -0
  31. package/lib/commands/create-args.d.ts +17 -0
  32. package/lib/commands/create-args.d.ts.map +1 -0
  33. package/lib/commands/create-args.js +53 -0
  34. package/lib/commands/create-args.js.map +1 -0
  35. package/lib/commands/create.d.ts +38 -0
  36. package/lib/commands/create.d.ts.map +1 -0
  37. package/lib/commands/create.js +43 -0
  38. package/lib/commands/create.js.map +1 -0
  39. package/lib/commands/delete-args.d.ts +17 -0
  40. package/lib/commands/delete-args.d.ts.map +1 -0
  41. package/lib/commands/delete-args.js +49 -0
  42. package/lib/commands/delete-args.js.map +1 -0
  43. package/lib/commands/delete.d.ts +30 -0
  44. package/lib/commands/delete.d.ts.map +1 -0
  45. package/lib/commands/delete.js +32 -0
  46. package/lib/commands/delete.js.map +1 -0
  47. package/lib/commands/generate-ast-builder.d.ts +1 -1
  48. package/lib/commands/generate-ast-builder.d.ts.map +1 -1
  49. package/lib/commands/generate-ast-builder.js +2 -11
  50. package/lib/commands/generate-ast-builder.js.map +1 -1
  51. package/lib/commands/generate-languages.d.ts +35 -0
  52. package/lib/commands/generate-languages.d.ts.map +1 -0
  53. package/lib/commands/generate-languages.js +105 -0
  54. package/lib/commands/generate-languages.js.map +1 -0
  55. package/lib/commands/generate-transfer-builder.d.ts +33 -0
  56. package/lib/commands/generate-transfer-builder.d.ts.map +1 -0
  57. package/lib/commands/generate-transfer-builder.js +86 -0
  58. package/lib/commands/generate-transfer-builder.js.map +1 -0
  59. package/lib/commands/generate-transfer-model-args.d.ts.map +1 -1
  60. package/lib/commands/generate-transfer-model-args.js +20 -5
  61. package/lib/commands/generate-transfer-model-args.js.map +1 -1
  62. package/lib/commands/generate-transfer-model-config.d.ts.map +1 -1
  63. package/lib/commands/generate-transfer-model-config.js +8 -3
  64. package/lib/commands/generate-transfer-model-config.js.map +1 -1
  65. package/lib/commands/generate-transfer-model.d.ts +41 -9
  66. package/lib/commands/generate-transfer-model.d.ts.map +1 -1
  67. package/lib/commands/generate-transfer-model.js +225 -68
  68. package/lib/commands/generate-transfer-model.js.map +1 -1
  69. package/lib/commands/generated-module-path.d.ts +16 -0
  70. package/lib/commands/generated-module-path.d.ts.map +1 -0
  71. package/lib/commands/generated-module-path.js +21 -0
  72. package/lib/commands/generated-module-path.js.map +1 -0
  73. package/lib/commands/harness-args.d.ts +46 -43
  74. package/lib/commands/harness-args.d.ts.map +1 -1
  75. package/lib/commands/harness-args.js +170 -29
  76. package/lib/commands/harness-args.js.map +1 -1
  77. package/lib/commands/headless-harness.d.ts +37 -20
  78. package/lib/commands/headless-harness.d.ts.map +1 -1
  79. package/lib/commands/headless-harness.js +71 -19
  80. package/lib/commands/headless-harness.js.map +1 -1
  81. package/lib/commands/init-args.d.ts +5 -18
  82. package/lib/commands/init-args.d.ts.map +1 -1
  83. package/lib/commands/init-args.js +131 -35
  84. package/lib/commands/init-args.js.map +1 -1
  85. package/lib/commands/init-hosts.d.ts +24 -0
  86. package/lib/commands/init-hosts.d.ts.map +1 -0
  87. package/lib/commands/init-hosts.js +37 -0
  88. package/lib/commands/init-hosts.js.map +1 -0
  89. package/lib/commands/init-prompt.d.ts +3 -3
  90. package/lib/commands/init-prompt.d.ts.map +1 -1
  91. package/lib/commands/init-prompt.js +4 -5
  92. package/lib/commands/init-prompt.js.map +1 -1
  93. package/lib/commands/init-skills.d.ts +41 -0
  94. package/lib/commands/init-skills.d.ts.map +1 -0
  95. package/lib/commands/init-skills.js +110 -0
  96. package/lib/commands/init-skills.js.map +1 -0
  97. package/lib/commands/init-templates.d.ts +20 -14
  98. package/lib/commands/init-templates.d.ts.map +1 -1
  99. package/lib/commands/init-templates.js +3134 -763
  100. package/lib/commands/init-templates.js.map +1 -1
  101. package/lib/commands/init-wizard.d.ts +10 -0
  102. package/lib/commands/init-wizard.d.ts.map +1 -1
  103. package/lib/commands/init-wizard.js +76 -31
  104. package/lib/commands/init-wizard.js.map +1 -1
  105. package/lib/commands/init-workspace.d.ts +13 -11
  106. package/lib/commands/init-workspace.d.ts.map +1 -1
  107. package/lib/commands/init-workspace.js +21 -7
  108. package/lib/commands/init-workspace.js.map +1 -1
  109. package/lib/commands/init.d.ts +61 -24
  110. package/lib/commands/init.d.ts.map +1 -1
  111. package/lib/commands/init.js +244 -50
  112. package/lib/commands/init.js.map +1 -1
  113. package/lib/commands/kebab.d.ts +15 -0
  114. package/lib/commands/kebab.d.ts.map +1 -0
  115. package/lib/commands/kebab.js +17 -0
  116. package/lib/commands/kebab.js.map +1 -0
  117. package/lib/commands/lint-grammar-args.d.ts +3 -2
  118. package/lib/commands/lint-grammar-args.d.ts.map +1 -1
  119. package/lib/commands/lint-grammar-args.js +14 -11
  120. package/lib/commands/lint-grammar-args.js.map +1 -1
  121. package/lib/commands/lint-grammar-driver.js +2 -1
  122. package/lib/commands/lint-grammar-driver.js.map +1 -1
  123. package/lib/commands/lint-grammar-report.js.map +1 -1
  124. package/lib/commands/lint-grammar.js +1 -1
  125. package/lib/commands/lint-grammar.js.map +1 -1
  126. package/lib/commands/measure-memory-args.d.ts +3 -2
  127. package/lib/commands/measure-memory-args.d.ts.map +1 -1
  128. package/lib/commands/measure-memory-args.js +26 -14
  129. package/lib/commands/measure-memory-args.js.map +1 -1
  130. package/lib/commands/measure-memory-driver.js +5 -3
  131. package/lib/commands/measure-memory-driver.js.map +1 -1
  132. package/lib/commands/measure-memory.d.ts +1 -1
  133. package/lib/commands/measure-memory.d.ts.map +1 -1
  134. package/lib/commands/measure-memory.js +6 -3
  135. package/lib/commands/measure-memory.js.map +1 -1
  136. package/lib/commands/message-catalogue-args.d.ts +16 -0
  137. package/lib/commands/message-catalogue-args.d.ts.map +1 -0
  138. package/lib/commands/message-catalogue-args.js +53 -0
  139. package/lib/commands/message-catalogue-args.js.map +1 -0
  140. package/lib/commands/message-catalogue.d.ts +21 -0
  141. package/lib/commands/message-catalogue.d.ts.map +1 -0
  142. package/lib/commands/message-catalogue.js +48 -0
  143. package/lib/commands/message-catalogue.js.map +1 -0
  144. package/lib/commands/model-docs-args.d.ts +4 -3
  145. package/lib/commands/model-docs-args.d.ts.map +1 -1
  146. package/lib/commands/model-docs-args.js +13 -11
  147. package/lib/commands/model-docs-args.js.map +1 -1
  148. package/lib/commands/model-docs-driver.js +2 -1
  149. package/lib/commands/model-docs-driver.js.map +1 -1
  150. package/lib/commands/model-docs.js +1 -1
  151. package/lib/commands/model-docs.js.map +1 -1
  152. package/lib/commands/projects-args.d.ts.map +1 -1
  153. package/lib/commands/projects-args.js +5 -5
  154. package/lib/commands/projects-args.js.map +1 -1
  155. package/lib/commands/projects.d.ts +3 -4
  156. package/lib/commands/projects.d.ts.map +1 -1
  157. package/lib/commands/projects.js +2 -2
  158. package/lib/commands/projects.js.map +1 -1
  159. package/lib/commands/query-args.d.ts.map +1 -1
  160. package/lib/commands/query-args.js +6 -5
  161. package/lib/commands/query-args.js.map +1 -1
  162. package/lib/commands/query.d.ts +6 -5
  163. package/lib/commands/query.d.ts.map +1 -1
  164. package/lib/commands/query.js +5 -4
  165. package/lib/commands/query.js.map +1 -1
  166. package/lib/commands/reflect-args.d.ts +3 -2
  167. package/lib/commands/reflect-args.d.ts.map +1 -1
  168. package/lib/commands/reflect-args.js +14 -11
  169. package/lib/commands/reflect-args.js.map +1 -1
  170. package/lib/commands/reflect-driver.js +2 -1
  171. package/lib/commands/reflect-driver.js.map +1 -1
  172. package/lib/commands/reflect-report.js.map +1 -1
  173. package/lib/commands/reflect.js +1 -1
  174. package/lib/commands/reflect.js.map +1 -1
  175. package/lib/commands/save-args.d.ts.map +1 -1
  176. package/lib/commands/save-args.js +7 -4
  177. package/lib/commands/save-args.js.map +1 -1
  178. package/lib/commands/save.d.ts +8 -4
  179. package/lib/commands/save.d.ts.map +1 -1
  180. package/lib/commands/save.js +12 -23
  181. package/lib/commands/save.js.map +1 -1
  182. package/lib/commands/skills.d.ts +22 -0
  183. package/lib/commands/skills.d.ts.map +1 -0
  184. package/lib/commands/skills.js +129 -0
  185. package/lib/commands/skills.js.map +1 -0
  186. package/lib/commands/validate-args.d.ts +3 -2
  187. package/lib/commands/validate-args.d.ts.map +1 -1
  188. package/lib/commands/validate-args.js +14 -11
  189. package/lib/commands/validate-args.js.map +1 -1
  190. package/lib/commands/validate-driver.js +2 -1
  191. package/lib/commands/validate-driver.js.map +1 -1
  192. package/lib/commands/validate-report.js.map +1 -1
  193. package/lib/commands/validate.js +1 -1
  194. package/lib/commands/validate.js.map +1 -1
  195. package/lib/commands/watch-args.d.ts.map +1 -1
  196. package/lib/commands/watch-args.js +6 -4
  197. package/lib/commands/watch-args.js.map +1 -1
  198. package/lib/commands/watch.d.ts +3 -4
  199. package/lib/commands/watch.d.ts.map +1 -1
  200. package/lib/commands/watch.js +5 -2
  201. package/lib/commands/watch.js.map +1 -1
  202. package/lib/driver-heap.d.ts +52 -0
  203. package/lib/driver-heap.d.ts.map +1 -0
  204. package/lib/driver-heap.js +51 -0
  205. package/lib/driver-heap.js.map +1 -0
  206. package/lib/index.d.ts +3 -0
  207. package/lib/index.d.ts.map +1 -1
  208. package/lib/index.js +3 -0
  209. package/lib/index.js.map +1 -1
  210. package/lib/log-level.d.ts +21 -11
  211. package/lib/log-level.d.ts.map +1 -1
  212. package/lib/log-level.js +25 -14
  213. package/lib/log-level.js.map +1 -1
  214. package/lib/spawn-data-server.d.ts +9 -4
  215. package/lib/spawn-data-server.d.ts.map +1 -1
  216. package/lib/spawn-data-server.js +5 -4
  217. package/lib/spawn-data-server.js.map +1 -1
  218. package/lib/stderr-connection-logger.d.ts +12 -0
  219. package/lib/stderr-connection-logger.d.ts.map +1 -0
  220. package/lib/stderr-connection-logger.js +16 -0
  221. package/lib/stderr-connection-logger.js.map +1 -0
  222. package/lib/testing/echo-server.js +9 -1
  223. package/lib/testing/echo-server.js.map +1 -1
  224. package/package.json +99 -41
  225. package/src/cli.ts +11 -2
  226. package/src/commands/analyze-heap-args.ts +1 -2
  227. package/src/commands/analyze-heap.ts +4 -1
  228. package/src/commands/ast-ground-truth-args.ts +16 -13
  229. package/src/commands/ast-ground-truth-driver.ts +4 -2
  230. package/src/commands/ast-ground-truth.ts +1 -1
  231. package/src/commands/check-skills-args.ts +70 -0
  232. package/src/commands/client-session.ts +33 -0
  233. package/src/commands/create-args.ts +68 -0
  234. package/src/commands/create.ts +83 -0
  235. package/src/commands/delete-args.ts +64 -0
  236. package/src/commands/delete.ts +61 -0
  237. package/src/commands/generate-ast-builder.ts +2 -12
  238. package/src/commands/generate-languages.ts +132 -0
  239. package/src/commands/generate-transfer-builder.ts +101 -0
  240. package/src/commands/generate-transfer-model-args.ts +20 -5
  241. package/src/commands/generate-transfer-model-config.ts +8 -3
  242. package/src/commands/generate-transfer-model.ts +297 -66
  243. package/src/commands/generated-module-path.ts +22 -0
  244. package/src/commands/harness-args.ts +163 -33
  245. package/src/commands/headless-harness.ts +89 -28
  246. package/src/commands/init-args.ts +135 -35
  247. package/src/commands/init-hosts.ts +51 -0
  248. package/src/commands/init-prompt.ts +5 -6
  249. package/src/commands/init-skills.ts +129 -0
  250. package/src/commands/init-templates.ts +3326 -785
  251. package/src/commands/init-wizard.ts +97 -32
  252. package/src/commands/init-workspace.ts +31 -16
  253. package/src/commands/init.ts +311 -65
  254. package/src/commands/kebab.ts +17 -0
  255. package/src/commands/lint-grammar-args.ts +18 -14
  256. package/src/commands/lint-grammar-driver.ts +2 -1
  257. package/src/commands/lint-grammar.ts +1 -1
  258. package/src/commands/measure-memory-args.ts +31 -17
  259. package/src/commands/measure-memory-driver.ts +5 -3
  260. package/src/commands/measure-memory.ts +6 -3
  261. package/src/commands/message-catalogue-args.ts +55 -0
  262. package/src/commands/message-catalogue.ts +56 -0
  263. package/src/commands/model-docs-args.ts +17 -14
  264. package/src/commands/model-docs-driver.ts +2 -1
  265. package/src/commands/model-docs.ts +1 -1
  266. package/src/commands/projects-args.ts +5 -4
  267. package/src/commands/projects.ts +4 -6
  268. package/src/commands/query-args.ts +6 -4
  269. package/src/commands/query.ts +9 -9
  270. package/src/commands/reflect-args.ts +18 -14
  271. package/src/commands/reflect-driver.ts +2 -1
  272. package/src/commands/reflect.ts +1 -1
  273. package/src/commands/save-args.ts +7 -3
  274. package/src/commands/save.ts +24 -27
  275. package/src/commands/skills.ts +146 -0
  276. package/src/commands/validate-args.ts +18 -14
  277. package/src/commands/validate-driver.ts +2 -1
  278. package/src/commands/validate.ts +1 -1
  279. package/src/commands/watch-args.ts +6 -3
  280. package/src/commands/watch.ts +7 -6
  281. package/src/driver-heap.ts +65 -0
  282. package/src/index.ts +3 -0
  283. package/src/log-level.ts +42 -14
  284. package/src/spawn-data-server.ts +17 -5
  285. package/src/stderr-connection-logger.ts +18 -0
  286. package/src/testing/echo-server.ts +11 -2
  287. package/templates/client/gitignore +3 -0
  288. package/templates/client/src/__GRAMMAR_ID__-diagram-module.ts +82 -0
  289. package/templates/editorconfig +15 -0
  290. package/templates/gitignore +1 -0
  291. package/templates/host-browser/esbuild.mjs +82 -0
  292. package/templates/host-browser/gitignore +4 -0
  293. package/templates/host-browser/hydranium-mark.svg +40 -0
  294. package/templates/host-browser/index.html +287 -0
  295. package/templates/host-browser/playwright.config.mts +24 -0
  296. package/templates/host-browser/src/data-status.ts +15 -0
  297. package/templates/host-browser/src/diagram-save.ts +60 -0
  298. package/templates/host-browser/src/diagram.ts +121 -0
  299. package/templates/host-browser/src/editor.ts +116 -0
  300. package/templates/host-browser/src/log.ts +14 -0
  301. package/templates/host-browser/src/monaco-editor-core-worker.d.ts +7 -0
  302. package/templates/host-browser/src/monaco-editor-worker.ts +10 -0
  303. package/templates/host-browser/src/posix-path-shim.ts +23 -0
  304. package/templates/host-browser/src/shown-file.ts +61 -0
  305. package/templates/host-browser/src/workspace.ts +5 -0
  306. package/templates/host-browser/tsconfig.e2e.json +16 -0
  307. package/templates/host-browser/tsconfig.page.json +16 -0
  308. package/templates/host-browser/tsconfig.worker.json +16 -0
  309. package/templates/host-theia-browser/esbuild.mjs +24 -0
  310. package/templates/host-theia-browser/gitignore +9 -0
  311. package/templates/host-theia-browser/playwright.config.mts +42 -0
  312. package/templates/host-theia-browser/start.mjs +50 -0
  313. package/templates/host-theia-browser/tsconfig.e2e.json +16 -0
  314. package/templates/host-theia-electron/esbuild.mjs +27 -0
  315. package/templates/host-theia-electron/gitignore +8 -0
  316. package/templates/host-theia-electron/playwright.config.mts +12 -0
  317. package/templates/host-theia-electron/start.mjs +47 -0
  318. package/templates/host-theia-electron/tsconfig.e2e.json +16 -0
  319. package/templates/host-vscode/esbuild.mjs +38 -0
  320. package/templates/host-vscode/gitignore +7 -0
  321. package/templates/host-vscode/playwright.config.mts +14 -0
  322. package/templates/host-vscode/src/__GRAMMAR_ID__-diagram-editor.ts +19 -0
  323. package/templates/host-vscode/src/show-model-command.ts +24 -0
  324. package/templates/host-vscode/src/webview/__GRAMMAR_ID__-diagram.ts +18 -0
  325. package/templates/host-vscode/src/webview/diagram.css +40 -0
  326. package/templates/host-vscode/start.mjs +22 -0
  327. package/templates/host-vscode/test/content-server.cjs +40 -0
  328. package/templates/host-vscode/test/install-vscode.mts +21 -0
  329. package/templates/host-vscode/test/virtual-documents.spec.mts +28 -0
  330. package/templates/host-vscode/test/vscode-version.mts +10 -0
  331. package/templates/host-vscode/tsconfig.e2e.json +17 -0
  332. package/templates/host-vscode/tsconfig.json +19 -0
  333. package/templates/host-vscode/tsconfig.webview.json +17 -0
  334. package/templates/oxlintrc.json +4 -0
  335. package/templates/protocol/gitignore +3 -0
  336. package/templates/protocol/src/__GRAMMAR_ID__-diagram-types.ts +47 -0
  337. package/templates/server/gitignore +6 -0
  338. package/templates/server/src/glsp/__GRAMMAR_ID__/create-node-operation-handler.ts +62 -0
  339. package/templates/server/src/glsp/__GRAMMAR_ID__/delete-operation-handler.ts +63 -0
  340. package/templates/server/src/glsp/__GRAMMAR_ID__/gmodel-factory.ts +144 -0
  341. package/templates/server/src/glsp/__GRAMMAR_ID__/state.ts +18 -0
  342. package/templates/server/src/glsp/__GRAMMAR_ID__/storage.ts +16 -0
  343. package/templates/server/src/glsp/__GRAMMAR_ID__/submission-handler.ts +24 -0
  344. package/templates/server/src/grammar/common.langium +12 -0
  345. package/templates/server/src/language-server/__GRAMMAR_ID__-semantic-tokens.ts +10 -0
  346. package/templates/server/src/language-server/__GRAMMAR_ID__-serializer.ts +53 -0
  347. package/templates/server/src/language-server/__GRAMMAR_ID__-validation.ts +30 -0
  348. package/templates/server/src/language-server/ast.ts +23 -0
  349. package/templates/server/src/node/services.ts +16 -0
  350. package/templates/server/test/__GRAMMAR_ID__-diagram.test.ts +403 -0
  351. package/templates/server/test/__GRAMMAR_ID__-semantic-tokens.test.ts +34 -0
  352. package/templates/server/test/tsconfig.json +4 -0
  353. package/templates/server/tsconfig.test.json +10 -0
  354. package/templates/server/vitest.config.ts +14 -0
  355. package/templates/theia/gitignore +3 -0
  356. package/templates/theia/src/browser/__GRAMMAR_ID__-diagram-frontend-module.ts +65 -0
  357. package/templates/theia/src/browser/__PROJECT_ID__-connection-preload-module.ts +15 -0
  358. package/templates/theia/src/browser/__PROJECT_ID__-data-connection.ts +15 -0
  359. package/templates/theia/src/browser/__PROJECT_ID__-data-port.ts +11 -0
  360. package/templates/theia/src/browser/__PROJECT_ID__-glsp-client-contribution.ts +13 -0
  361. package/templates/theia/src/browser/__PROJECT_ID__-show-model-command.ts +51 -0
  362. package/templates/theia/src/common/__PROJECT_ID__-glsp-contribution.ts +3 -0
  363. package/templates/theia/src/node/__PROJECT_ID__-connection-backend-module.ts +12 -0
  364. package/templates/theia/src/node/__PROJECT_ID__-data-backend-module.ts +15 -0
  365. package/templates/theia/src/node/__PROJECT_ID__-glsp-backend-module.ts +16 -0
  366. package/templates/theia/style/diagram.css +20 -0
  367. package/templates/theia/tsconfig.json +24 -0
  368. package/templates/vscode-servers/gitignore +4 -0
  369. package/templates/vscode-servers/tsconfig.json +19 -0
  370. package/templates/workspace/nodes.__EXTENSION__ +5 -0
  371. package/templates/workspace/references.__EXTENSION__ +2 -0
@@ -9,34 +9,36 @@
9
9
 
10
10
  import {
11
11
  exitWithUsage,
12
+ HARNESS_VALUE_FLAGS,
12
13
  helpRequested,
13
- LOG_LEVEL_FLAG,
14
- logLevelHelpLine,
15
- logLevelOption,
14
+ importHelpLines,
15
+ LOG_VALUE_FLAGS,
16
+ logHelpLines,
17
+ logOptions,
16
18
  parseHarnessArgs,
17
19
  printHelp,
18
- SERVICES_FLAG,
19
20
  type UsageError
20
21
  } from './harness-args.js';
21
22
  import { runLintGrammar, type LintGrammarCommandOptions } from './lint-grammar.js';
22
23
 
23
- const VALUE_FLAGS = [LOG_LEVEL_FLAG] as const;
24
+ const VALUE_FLAGS = [...LOG_VALUE_FLAGS] as const;
24
25
  const BOOL_FLAGS = ['--strict', '--json'] as const;
25
26
  const REPEATABLE_VALUE_FLAGS = ['--name-property'] as const;
26
27
 
27
28
  /**
28
29
  * Every flag `lint-grammar` accepts, derived from the sets the parser is handed
29
- * so the list cannot claim a flag the parser would reject. `--services` is
30
- * consumed by the shared harness parser itself, so it is in neither set.
30
+ * so the list cannot claim a flag the parser would reject.
31
+ * {@link HARNESS_VALUE_FLAGS} are consumed by the shared harness parser itself,
32
+ * so they are in neither set.
31
33
  */
32
- export const LINT_GRAMMAR_FLAGS: readonly string[] = [SERVICES_FLAG, ...REPEATABLE_VALUE_FLAGS, ...VALUE_FLAGS, ...BOOL_FLAGS];
34
+ export const LINT_GRAMMAR_FLAGS: readonly string[] = [...HARNESS_VALUE_FLAGS, ...REPEATABLE_VALUE_FLAGS, ...VALUE_FLAGS, ...BOOL_FLAGS];
33
35
 
34
36
  /** The subset that takes a value, so `--help` in a value position reads as data. */
35
- export const LINT_GRAMMAR_VALUE_FLAGS: readonly string[] = [SERVICES_FLAG, ...REPEATABLE_VALUE_FLAGS, ...VALUE_FLAGS];
37
+ export const LINT_GRAMMAR_VALUE_FLAGS: readonly string[] = [...HARNESS_VALUE_FLAGS, ...REPEATABLE_VALUE_FLAGS, ...VALUE_FLAGS];
36
38
 
37
39
  /** The `--help` text, as data, held to {@link LINT_GRAMMAR_FLAGS} by a test. */
38
40
  export const LINT_GRAMMAR_HELP: readonly string[] = [
39
- 'Usage: hydranium-cli lint-grammar --services <module> [--name-property <p>]... [--strict] [--json] [--log-level <lvl>]',
41
+ 'Usage: hydranium-cli lint-grammar [--services <module>] [--import <specifier>]... [--name-property <p>]... [--strict] [--json] [--log-level <lvl>] [--log-file <file>] [--log-file-level <lvl>]',
40
42
  '',
41
43
  "Check a head's grammar against the framework's conventions — a CI gate: the",
42
44
  'process exits non-zero when a violation is found. Read-only: no workspace is',
@@ -47,26 +49,28 @@ export const LINT_GRAMMAR_HELP: readonly string[] = [
47
49
  'zero-arg `createServices(): { shared }` thunk. Needs @hydranium/core.',
48
50
  '',
49
51
  'Options:',
50
- ' --services <module> ESM module exporting `createServices(): { shared }` (required).',
52
+ ' --services <module> ESM module exporting `createServices(): { shared }` (required) unless package.json sets hydranium.services.',
53
+ ...importHelpLines(23),
51
54
  ' --name-property <p> Property that satisfies the nameability convention',
52
55
  ' (repeatable). Default: name.',
53
56
  ' --strict Also fail (non-zero exit) on warnings, not only errors.',
54
57
  ' --json Emit the raw JSON result instead of the human report.',
55
- logLevelHelpLine(23)
58
+ ...logHelpLines(23)
56
59
  ];
57
60
 
58
61
  export function parseLintGrammarArgs(args: string[], onError: UsageError = exitWithUsage): LintGrammarCommandOptions {
59
- const { servicesModule, options, values } = parseHarnessArgs(args, 'lint-grammar', VALUE_FLAGS, BOOL_FLAGS, {
62
+ const { servicesModule, imports, options, values } = parseHarnessArgs(args, 'lint-grammar', VALUE_FLAGS, BOOL_FLAGS, {
60
63
  requireWorkspace: false,
61
64
  repeatableValueFlags: REPEATABLE_VALUE_FLAGS,
62
65
  onError
63
66
  });
64
67
  return {
65
68
  servicesModule,
69
+ imports,
66
70
  nameProperties: values['--name-property'],
67
71
  strict: options['--strict'] === 'true',
68
72
  json: options['--json'] === 'true',
69
- logLevel: logLevelOption(options[LOG_LEVEL_FLAG])
73
+ ...logOptions(options)
70
74
  };
71
75
  }
72
76
 
@@ -16,6 +16,7 @@
16
16
  * only spawned.
17
17
  */
18
18
 
19
+ import { describeError } from '@hydranium/protocol';
19
20
  import { loadHeadlessContext } from './headless-harness.js';
20
21
  import { formatLintReport, lintExitCode } from './lint-grammar-report.js';
21
22
 
@@ -78,6 +79,6 @@ async function main(argv: string[]): Promise<number> {
78
79
  main(process.argv.slice(2))
79
80
  .then(code => process.exit(code))
80
81
  .catch((error: unknown) => {
81
- console.error(error instanceof Error ? error.message : String(error));
82
+ console.error(describeError(error));
82
83
  process.exit(1);
83
84
  });
@@ -53,5 +53,5 @@ export function buildLintGrammarDriverArgs(options: LintGrammarCommandOptions):
53
53
  * `createServices` module, keeping the binary language-agnostic.
54
54
  */
55
55
  export function runLintGrammar(options: LintGrammarCommandOptions): Promise<void> {
56
- return runDriverChild(['--max-old-space-size=8192', DRIVER, ...buildLintGrammarDriverArgs(options)], options);
56
+ return runDriverChild([DRIVER, ...buildLintGrammarDriverArgs(options)], options);
57
57
  }
@@ -7,16 +7,19 @@
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
9
 
10
+ import { describeError } from '@hydranium/protocol';
10
11
  import {
11
12
  exitWithUsage,
13
+ HARNESS_VALUE_FLAGS,
12
14
  helpRequested,
13
- LOG_LEVEL_FLAG,
14
- logLevelHelpLine,
15
- logLevelOption,
15
+ importHelpLines,
16
+ LOG_FILE_FLAG,
17
+ LOG_VALUE_FLAGS,
18
+ logHelpLines,
19
+ logOptions,
16
20
  numericOption,
17
21
  parseHarnessArgs,
18
22
  printHelp,
19
- SERVICES_FLAG,
20
23
  type UsageError
21
24
  } from './harness-args.js';
22
25
  import { parseProfileDimensions, runMeasureMemory, type MeasureMemoryCommandOptions } from './measure-memory.js';
@@ -29,23 +32,24 @@ const VALUE_FLAGS = [
29
32
  '--snapshot-path',
30
33
  '--profile',
31
34
  '--session-out',
32
- LOG_LEVEL_FLAG
35
+ ...LOG_VALUE_FLAGS
33
36
  ] as const;
34
37
  const BOOL_FLAGS = ['--snapshot', '--json'] as const;
35
38
 
36
39
  /**
37
40
  * Every flag `measure-memory` accepts, derived from the sets the parser is
38
- * handed so the list cannot claim a flag the parser would reject. `--services`
39
- * is consumed by the shared harness parser itself, so it is in neither set.
41
+ * handed so the list cannot claim a flag the parser would reject.
42
+ * {@link HARNESS_VALUE_FLAGS} are consumed by the shared harness parser itself,
43
+ * so they are in neither set.
40
44
  */
41
- export const MEASURE_MEMORY_FLAGS: readonly string[] = [SERVICES_FLAG, ...VALUE_FLAGS, ...BOOL_FLAGS];
45
+ export const MEASURE_MEMORY_FLAGS: readonly string[] = [...HARNESS_VALUE_FLAGS, ...VALUE_FLAGS, ...BOOL_FLAGS];
42
46
 
43
47
  /** The subset that takes a value, so `--help` in a value position reads as data. */
44
- export const MEASURE_MEMORY_VALUE_FLAGS: readonly string[] = [SERVICES_FLAG, ...VALUE_FLAGS];
48
+ export const MEASURE_MEMORY_VALUE_FLAGS: readonly string[] = [...HARNESS_VALUE_FLAGS, ...VALUE_FLAGS];
45
49
 
46
50
  /** The `--help` text, as data, held to {@link MEASURE_MEMORY_FLAGS} by a test. */
47
51
  export const MEASURE_MEMORY_HELP: readonly string[] = [
48
- 'Usage: hydranium-cli measure-memory --services <module> <workspace> [options]',
52
+ 'Usage: hydranium-cli measure-memory [--services <module>] [--import <specifier>]... <workspace> [options]',
49
53
  '',
50
54
  'Measure model-store memory for a workspace. `<module>` is an ESM module that',
51
55
  'exports a zero-arg `createServices(): { shared }` thunk (the head wires its own',
@@ -53,7 +57,8 @@ export const MEASURE_MEMORY_HELP: readonly string[] = [
53
57
  'baseline / after-build / churn lines print on stdout. Needs @hydranium/core.',
54
58
  '',
55
59
  'Options:',
56
- ' --services <module> ESM module exporting `createServices(): { shared }` (required).',
60
+ ' --services <module> ESM module exporting `createServices(): { shared }` (required) unless package.json sets hydranium.services.',
61
+ ...importHelpLines(22),
57
62
  ' <workspace> Workspace root (path or file URI) to build (required).',
58
63
  ' --edits <N> Rebuild-churn cycles to probe for retention. Default: 0 (skip).',
59
64
  ' --edit-docs <N> Documents to churn per cycle. Default: 25.',
@@ -64,14 +69,17 @@ export const MEASURE_MEMORY_HELP: readonly string[] = [
64
69
  ' measure the pre-shed (always-keep) baseline.',
65
70
  ' --snapshot Write a `.heapsnapshot` after the build.',
66
71
  ' --snapshot-path <p> Snapshot path. Default: <cwd>/<workspace-basename>.heapsnapshot.',
67
- ' --profile <dims> Capture sampled profiles around the build (+churn) into a',
68
- ' profiling session. Comma-separated: cpu,alloc,gc,eld,heap.',
72
+ ' --profile <dims> Capture profiles around the build (+churn) into a',
73
+ ' profiling session. Comma-separated: cpu,alloc,gc,eld,heap,framework.',
74
+ ' framework instruments named passes and adds timing overhead.',
69
75
  ' --session-out <dir> Parent directory for the profiling session folder (with --profile).',
76
+ ' The session logs to its server.log at --log-file-level, else at',
77
+ ' --log-level, else info; --log-file is refused beside --profile.',
70
78
  ' --json Emit the measurement as one JSON document instead of the',
71
79
  ' progress lines: documentCount, buildMs, emptyHeapBytes,',
72
80
  ' afterBuildHeapBytes, and churnGrowthBytes / snapshotPath /',
73
81
  ' profilingSession where the run produced them.',
74
- logLevelHelpLine(22)
82
+ ...logHelpLines(22)
75
83
  ];
76
84
 
77
85
  /**
@@ -91,15 +99,21 @@ function validatedProfile(csv: string | undefined, onError: UsageError): string
91
99
  try {
92
100
  parseProfileDimensions(csv);
93
101
  } catch (err: unknown) {
94
- onError(`Option --profile: ${err instanceof Error ? err.message : String(err)}`);
102
+ onError(`Option --profile: ${describeError(err)}`);
95
103
  }
96
104
  return csv;
97
105
  }
98
106
 
99
107
  export function parseMeasureMemoryArgs(args: string[], onError: UsageError = exitWithUsage): MeasureMemoryCommandOptions {
100
- const { servicesModule, workspace, options } = parseHarnessArgs(args, 'measure-memory', VALUE_FLAGS, BOOL_FLAGS, { onError });
108
+ const { servicesModule, imports, workspace, options } = parseHarnessArgs(args, 'measure-memory', VALUE_FLAGS, BOOL_FLAGS, { onError });
109
+ // The profiling session points the log at its own `server.log`, which would
110
+ // replace the requested file without a word.
111
+ if (options['--profile'] !== undefined && options[LOG_FILE_FLAG] !== undefined) {
112
+ onError(`${LOG_FILE_FLAG} cannot be combined with --profile, which logs to the session's server.log`);
113
+ }
101
114
  return {
102
115
  servicesModule,
116
+ imports,
103
117
  workspace,
104
118
  editCycles: numericOption(options['--edits'], '--edits', onError),
105
119
  editDocs: numericOption(options['--edit-docs'], '--edit-docs', onError),
@@ -110,7 +124,7 @@ export function parseMeasureMemoryArgs(args: string[], onError: UsageError = exi
110
124
  profile: validatedProfile(options['--profile'], onError),
111
125
  sessionOut: options['--session-out'],
112
126
  json: options['--json'] === 'true',
113
- logLevel: logLevelOption(options[LOG_LEVEL_FLAG])
127
+ ...logOptions(options)
114
128
  };
115
129
  }
116
130
 
@@ -9,12 +9,14 @@
9
9
 
10
10
  /*
11
11
  * Spawned child of the `measure-memory` subcommand. Launched by the parent with
12
- * `node --expose-gc --max-old-space-size=8192 <this> --services <module> <workspace> ...`
13
- * so the underlying harness gets post-GC readings. It dynamic-imports the head's
12
+ * `node [heap ceiling] --expose-gc <this> --services <module> <workspace> ...`
13
+ * so the underlying harness gets post-GC readings. The ceiling is whatever
14
+ * `driverHeapArgs` decides, which is nothing at all inside a container. It dynamic-imports the head's
14
15
  * services module and runs the framework's `measureModelMemory`, streaming the
15
16
  * baseline / after-build / churn lines to stdout. Never imported — only spawned.
16
17
  */
17
18
 
19
+ import { describeError } from '@hydranium/protocol';
18
20
  import { loadHeadlessContext } from './headless-harness.js';
19
21
  import { parseProfileDimensions } from './measure-memory.js';
20
22
 
@@ -123,6 +125,6 @@ async function main(argv: string[]): Promise<void> {
123
125
  main(process.argv.slice(2))
124
126
  .then(() => process.exit(0))
125
127
  .catch((error: unknown) => {
126
- console.error(error instanceof Error ? error.message : String(error));
128
+ console.error(describeError(error));
127
129
  process.exit(1);
128
130
  });
@@ -56,7 +56,7 @@ export interface MeasureMemoryCommandOptions extends DriverSpawnOptions {
56
56
  }
57
57
 
58
58
  /**
59
- * Parse a `--profile` dimension list (`cpu,alloc,gc,eld,heap`) into
59
+ * Parse a `--profile` dimension list (`cpu,alloc,gc,eld,heap,framework`) into
60
60
  * {@link ProfileCaptureOptions}. Case- and whitespace-tolerant; throws on an
61
61
  * unknown token so a typo fails loud rather than silently capturing nothing.
62
62
  */
@@ -68,6 +68,9 @@ export function parseProfileDimensions(csv: string): ProfileCaptureOptions {
68
68
  continue;
69
69
  }
70
70
  switch (token) {
71
+ case 'framework':
72
+ options.frameworkPasses = true;
73
+ break;
71
74
  case 'cpu':
72
75
  options.cpu = true;
73
76
  break;
@@ -88,7 +91,7 @@ export function parseProfileDimensions(csv: string): ProfileCaptureOptions {
88
91
  options.heapSnapshot = true;
89
92
  break;
90
93
  default:
91
- throw new Error(`Unknown profile dimension: ${token} (expected cpu, alloc, gc, eld, heap)`);
94
+ throw new Error(`Unknown profile dimension: ${token} (expected cpu, alloc, gc, eld, heap, framework)`);
92
95
  }
93
96
  }
94
97
  return options;
@@ -139,5 +142,5 @@ export function buildDriverArgs(options: MeasureMemoryCommandOptions): string[]
139
142
  * module and reports the baseline / after-build / churn lines on stdout.
140
143
  */
141
144
  export function runMeasureMemory(options: MeasureMemoryCommandOptions): Promise<void> {
142
- return runDriverChild(['--expose-gc', '--max-old-space-size=8192', DRIVER, ...buildDriverArgs(options)], options);
145
+ return runDriverChild(['--expose-gc', DRIVER, ...buildDriverArgs(options)], options);
143
146
  }
@@ -0,0 +1,55 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+
10
+ import { assertRequired, exitWithUsage, helpRequested, printHelp, type UsageError } from './harness-args.js';
11
+ import { runMessageCatalogue, type MessageCatalogueCommandOptions } from './message-catalogue.js';
12
+
13
+ export const MESSAGE_CATALOGUE_FLAGS: readonly string[] = ['--barrel', '--out-file'];
14
+ export const MESSAGE_CATALOGUE_VALUE_FLAGS = MESSAGE_CATALOGUE_FLAGS;
15
+ export const MESSAGE_CATALOGUE_HELP: readonly string[] = [
16
+ 'Usage: hydranium-cli message-catalogue --barrel <module>... [--out-file <file>]',
17
+ '',
18
+ 'Emit a flat JSON starter catalogue mapping message codes to English defaults.',
19
+ 'Modules are resolved from the current project and must be built first.',
20
+ 'Repeat --barrel for each framework head and your own messages. No server starts.',
21
+ '',
22
+ 'Options:',
23
+ ' --barrel <module> Messages package specifier or ESM file (required). Repeatable.',
24
+ ' --out-file <file> Write JSON here instead of stdout, after all imports succeed.'
25
+ ];
26
+
27
+ export function parseMessageCatalogueArgs(args: string[], onError: UsageError = exitWithUsage): MessageCatalogueCommandOptions {
28
+ const barrels: string[] = [];
29
+ let outFile: string | undefined;
30
+ for (let index = 0; index < args.length; index++) {
31
+ const flag = args[index];
32
+ if (!MESSAGE_CATALOGUE_FLAGS.includes(flag)) {
33
+ return onError(`Unexpected argument: ${flag} (hydranium-cli message-catalogue --help)`);
34
+ }
35
+ const value = args[++index];
36
+ if (value === undefined || value.startsWith('--')) {
37
+ return onError(`Missing value for ${flag}`);
38
+ }
39
+ if (flag === '--barrel') {
40
+ barrels.push(value);
41
+ } else {
42
+ outFile = value;
43
+ }
44
+ }
45
+ assertRequired(barrels[0], '--barrel', 'message-catalogue', onError);
46
+ return { barrels, outFile };
47
+ }
48
+
49
+ export async function runMessageCatalogueCommand(args: string[]): Promise<void> {
50
+ if (helpRequested(args, MESSAGE_CATALOGUE_VALUE_FLAGS)) {
51
+ printHelp(MESSAGE_CATALOGUE_HELP);
52
+ return;
53
+ }
54
+ await runMessageCatalogue(parseMessageCatalogueArgs(args));
55
+ }
@@ -0,0 +1,56 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+
10
+ import { collectMessages, type MessageCatalogue } from '@hydranium/protocol';
11
+ import { resolve as resolveModule } from 'import-meta-resolve';
12
+ import { isAbsolute, resolve } from 'node:path';
13
+ import { pathToFileURL } from 'node:url';
14
+ import { emitReport } from './headless-harness.js';
15
+
16
+ /**
17
+ * Enumerate declarations rather than scanning source. Conflicting defaults
18
+ * must fail before any output is written, or import order chooses the English.
19
+ */
20
+ export function createMessageCatalogue(barrels: readonly object[]): MessageCatalogue {
21
+ const entries = new Map<string, string>();
22
+ for (const barrel of barrels) {
23
+ for (const message of collectMessages(barrel)) {
24
+ const previous = entries.get(message.code);
25
+ if (previous !== undefined && previous !== message.text) {
26
+ throw new Error(`Conflicting English defaults for message '${message.code}'.`);
27
+ }
28
+ entries.set(message.code, message.text);
29
+ }
30
+ }
31
+ return Object.fromEntries([...entries].sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)));
32
+ }
33
+
34
+ export interface MessageCatalogueCommandOptions {
35
+ readonly barrels: readonly string[];
36
+ readonly outFile?: string;
37
+ }
38
+
39
+ /** Resolve against the caller's project, including when the CLI is installed globally. */
40
+ export async function runMessageCatalogue(options: MessageCatalogueCommandOptions): Promise<void> {
41
+ const projectUrl = pathToFileURL(resolve('package.json')).href;
42
+ const barrels: object[] = [];
43
+ for (const specifier of options.barrels) {
44
+ const target =
45
+ specifier.startsWith('.') || isAbsolute(specifier) ? pathToFileURL(resolve(specifier)).href : resolveModule(specifier, projectUrl);
46
+ const barrel = (await import(target)) as object;
47
+ if (collectMessages(barrel).length === 0) {
48
+ throw new Error(`Message barrel '${specifier}' exports no declarations. Pass a built messages module.`);
49
+ }
50
+ barrels.push(barrel);
51
+ }
52
+ if (barrels.length === 0) {
53
+ throw new Error('Pass at least one --barrel messages module.');
54
+ }
55
+ emitReport(JSON.stringify(createMessageCatalogue(barrels), undefined, 2), options.outFile);
56
+ }
@@ -9,33 +9,35 @@
9
9
 
10
10
  import {
11
11
  exitWithUsage,
12
+ HARNESS_VALUE_FLAGS,
12
13
  helpRequested,
13
- LOG_LEVEL_FLAG,
14
- logLevelHelpLine,
15
- logLevelOption,
14
+ importHelpLines,
15
+ LOG_VALUE_FLAGS,
16
+ logHelpLines,
17
+ logOptions,
16
18
  parseHarnessArgs,
17
19
  printHelp,
18
- SERVICES_FLAG,
19
20
  type UsageError
20
21
  } from './harness-args.js';
21
22
  import { OUT_FILE_FLAG } from './headless-harness.js';
22
23
  import { runModelDocs, type ModelDocsCommandOptions } from './model-docs.js';
23
24
 
24
- const VALUE_FLAGS = [OUT_FILE_FLAG, LOG_LEVEL_FLAG] as const;
25
+ const VALUE_FLAGS = [OUT_FILE_FLAG, ...LOG_VALUE_FLAGS] as const;
25
26
 
26
27
  /**
27
- * Every flag `model-docs` accepts, derived from the sets the parser is handed so
28
- * the list cannot claim a flag the parser would reject. `--services` is consumed
29
- * by the shared harness parser itself, so it is in neither set.
28
+ * Every flag `model-docs` accepts, derived from the sets the parser is handed
29
+ * so the list cannot claim a flag the parser would reject.
30
+ * {@link HARNESS_VALUE_FLAGS} are consumed by the shared harness parser itself,
31
+ * so they are in neither set.
30
32
  */
31
- export const MODEL_DOCS_FLAGS: readonly string[] = [SERVICES_FLAG, ...VALUE_FLAGS];
33
+ export const MODEL_DOCS_FLAGS: readonly string[] = [...HARNESS_VALUE_FLAGS, ...VALUE_FLAGS];
32
34
 
33
35
  /** The subset that takes a value, so `--help` in a value position reads as data. */
34
36
  export const MODEL_DOCS_VALUE_FLAGS: readonly string[] = MODEL_DOCS_FLAGS;
35
37
 
36
38
  /** The `--help` text, as data, held to {@link MODEL_DOCS_FLAGS} by a test. */
37
39
  export const MODEL_DOCS_HELP: readonly string[] = [
38
- 'Usage: hydranium-cli model-docs --services <module> [--out-file <file>] [--log-level <lvl>]',
40
+ 'Usage: hydranium-cli model-docs [--services <module>] [--import <specifier>]... [--out-file <file>] [--log-level <lvl>] [--log-file <file>] [--log-file-level <lvl>]',
39
41
  '',
40
42
  'Generate a navigable Markdown reference of every AST node type — a type index,',
41
43
  'cross-linked super/sub types, a reverse "referenced by" index, and a per-language',
@@ -45,19 +47,20 @@ export const MODEL_DOCS_HELP: readonly string[] = [
45
47
  'zero-arg `createServices(): { shared }` thunk. Needs @hydranium/core.',
46
48
  '',
47
49
  'Options:',
48
- ' --services <module> ESM module exporting `createServices(): { shared }` (required).',
50
+ ' --services <module> ESM module exporting `createServices(): { shared }` (required) unless package.json sets hydranium.services.',
51
+ ...importHelpLines(22),
49
52
  ' --out-file <file> Write the Markdown to this file instead of stdout. Written',
50
53
  ' only once the report exists, unlike a shell redirection,',
51
54
  ' which truncates the file before the head is even booted.',
52
- logLevelHelpLine(22)
55
+ ...logHelpLines(22)
53
56
  ];
54
57
 
55
58
  export function parseModelDocsArgs(args: string[], onError: UsageError = exitWithUsage): ModelDocsCommandOptions {
56
- const { servicesModule, options } = parseHarnessArgs(args, 'model-docs', VALUE_FLAGS, [], {
59
+ const { servicesModule, imports, options } = parseHarnessArgs(args, 'model-docs', VALUE_FLAGS, [], {
57
60
  requireWorkspace: false,
58
61
  onError
59
62
  });
60
- return { servicesModule, outFile: options[OUT_FILE_FLAG], logLevel: logLevelOption(options[LOG_LEVEL_FLAG]) };
63
+ return { servicesModule, imports, outFile: options[OUT_FILE_FLAG], ...logOptions(options) };
61
64
  }
62
65
 
63
66
  export function runModelDocsCommand(args: string[]): Promise<void> {
@@ -16,6 +16,7 @@
16
16
  * head throws. Never imported — only spawned.
17
17
  */
18
18
 
19
+ import { describeError } from '@hydranium/protocol';
19
20
  import { emitReport, loadHeadlessContext, OUT_FILE_FLAG } from './headless-harness.js';
20
21
  import { formatModelDocs } from './model-docs-report.js';
21
22
 
@@ -63,6 +64,6 @@ async function main(argv: string[]): Promise<number> {
63
64
  main(process.argv.slice(2))
64
65
  .then(code => process.exit(code))
65
66
  .catch((error: unknown) => {
66
- console.error(error instanceof Error ? error.message : String(error));
67
+ console.error(describeError(error));
67
68
  process.exit(1);
68
69
  });
@@ -44,5 +44,5 @@ export function buildModelDocsDriverArgs(options: ModelDocsCommandOptions): stri
44
44
  * module, keeping the binary language-agnostic.
45
45
  */
46
46
  export function runModelDocs(options: ModelDocsCommandOptions): Promise<void> {
47
- return runDriverChild(['--max-old-space-size=8192', DRIVER, ...buildModelDocsDriverArgs(options)], options);
47
+ return runDriverChild([DRIVER, ...buildModelDocsDriverArgs(options)], options);
48
48
  }
@@ -10,6 +10,7 @@
10
10
  import {
11
11
  exitWithUsage,
12
12
  helpRequested,
13
+ logHelpLines,
13
14
  parseFlagOptions,
14
15
  parseServerSpawnOptions,
15
16
  printHelp,
@@ -32,7 +33,7 @@ export const PROJECTS_VALUE_FLAGS: readonly string[] = PROJECTS_FLAGS;
32
33
 
33
34
  /** The `--help` text, as data, held to {@link PROJECTS_FLAGS} by a test. */
34
35
  export const PROJECTS_HELP: readonly string[] = [
35
- 'Usage: hydranium-cli projects --server "<cmd> [args...]" [--cwd <dir>] [--log-level <level>]',
36
+ 'Usage: hydranium-cli projects --server "<cmd> [args...]" [--cwd <dir>] [--log-level <lvl>] [--log-file <file>] [--log-file-level <lvl>]',
36
37
  '',
37
38
  'List projects exposed by the data-server subprocess. Output is newline-delimited',
38
39
  'JSON — one project envelope per line.',
@@ -40,17 +41,17 @@ export const PROJECTS_HELP: readonly string[] = [
40
41
  'Options:',
41
42
  ' --server "<cmd>" Command-line for the data-server subprocess (required).',
42
43
  ' --cwd <dir> Working directory for the spawned child. Default: cwd.',
43
- ' --log-level <lvl> Log threshold for the spawned server (off|error|warn|info|debug|trace).'
44
+ ...logHelpLines(19, 'the spawned server')
44
45
  ];
45
46
 
46
47
  export function parseProjectsArgs(args: string[], onError: UsageError = exitWithUsage): ProjectsCommandOptions {
47
- const { serverCommand, serverArgs, cwd, logLevel, extra } = parseServerSpawnOptions(args, 'projects', onError);
48
+ const { serverCommand, serverArgs, cwd, logLevel, logFile, logFileLevel, extra } = parseServerSpawnOptions(args, 'projects', onError);
48
49
  // `projects` declares no options beyond the shared ones, so nothing may
49
50
  // survive the spawn parser. Draining `extra` against an empty set is what
50
51
  // makes a typo an error here rather than a flag that silently did nothing —
51
52
  // the siblings get this from the option list they pass.
52
53
  parseFlagOptions(extra, 'projects', [], onError);
53
- return { serverCommand, serverArgs, cwd, logLevel };
54
+ return { serverCommand, serverArgs, cwd, logLevel, logFile, logFileLevel };
54
55
  }
55
56
 
56
57
  export function runProjectsCommand(args: string[]): Promise<void> {
@@ -7,9 +7,9 @@
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
9
 
10
- import type { LogThreshold, Project, TransferElement } from '@hydranium/protocol';
10
+ import type { Project, TransferElement } from '@hydranium/protocol';
11
11
  import type { DataServerProtocol } from '@hydranium/protocol/data';
12
- import { logLevelEnv } from '../log-level.js';
12
+ import { logEnv, type LogOptions } from '../log-level.js';
13
13
  import { withDataServer } from '../spawn-data-server.js';
14
14
 
15
15
  /**
@@ -17,7 +17,7 @@ import { withDataServer } from '../spawn-data-server.js';
17
17
  * `serverArgs` mirror what an adopter would pass to spawn the data-server
18
18
  * subprocess.
19
19
  */
20
- export interface ProjectsCommandOptions {
20
+ export interface ProjectsCommandOptions extends LogOptions {
21
21
  /**
22
22
  * Command-line tokens used to spawn the data-server child. Mirrors
23
23
  * the `--server "<cmd> [args...]"` shape on the CLI surface — split
@@ -26,8 +26,6 @@ export interface ProjectsCommandOptions {
26
26
  readonly serverCommand: string;
27
27
  readonly serverArgs?: readonly string[];
28
28
  readonly cwd?: string;
29
- /** Log threshold for the spawned server, set on its `HYDRANIUM_LOG_LEVEL` env. */
30
- readonly logLevel?: LogThreshold;
31
29
  /**
32
30
  * Output sink. Default: `process.stdout.write`. Tests inject a
33
31
  * capturing stub.
@@ -60,7 +58,7 @@ export async function runProjects(options: ProjectsCommandOptions): Promise<void
60
58
  command: options.serverCommand,
61
59
  args: options.serverArgs,
62
60
  cwd: options.cwd,
63
- env: options.logLevel ? logLevelEnv(options.logLevel) : undefined
61
+ env: logEnv(options)
64
62
  },
65
63
  async server => {
66
64
  const projects = await server.getProjects();
@@ -11,6 +11,7 @@ import {
11
11
  assertRequired,
12
12
  exitWithUsage,
13
13
  helpRequested,
14
+ logHelpLines,
14
15
  parseFlagOptions,
15
16
  parseServerSpawnOptions,
16
17
  printHelp,
@@ -35,21 +36,22 @@ export const QUERY_VALUE_FLAGS: readonly string[] = QUERY_FLAGS;
35
36
 
36
37
  /** The `--help` text, as data, held to {@link QUERY_FLAGS} by a test. */
37
38
  export const QUERY_HELP: readonly string[] = [
38
- 'Usage: hydranium-cli query --server "<cmd> [args...]" --uri <uri> [--cwd <dir>] [--log-level <level>]',
39
+ 'Usage: hydranium-cli query --server "<cmd> [args...]" --uri <uri> [--cwd <dir>] [--log-level <lvl>] [--log-file <file>] [--log-file-level <lvl>]',
39
40
  '',
40
41
  'Print the data-server document envelope for `<uri>` as a single JSON line.',
42
+ 'Fails when the server holds no document at `<uri>`.',
41
43
  '',
42
44
  'Options:',
43
45
  ' --server "<cmd>" Command-line for the data-server subprocess (required).',
44
46
  ' --uri <uri> Document URI (required).',
45
47
  ' --cwd <dir> Working directory for the spawned child. Default: cwd.',
46
- ' --log-level <lvl> Log threshold for the spawned server (off|error|warn|info|debug|trace).'
48
+ ...logHelpLines(19, 'the spawned server')
47
49
  ];
48
50
 
49
51
  export function parseQueryArgs(args: string[], onError: UsageError = exitWithUsage): QueryCommandOptions {
50
- const { serverCommand, serverArgs, cwd, logLevel, extra } = parseServerSpawnOptions(args, 'query', onError);
52
+ const { serverCommand, serverArgs, cwd, logLevel, logFile, logFileLevel, extra } = parseServerSpawnOptions(args, 'query', onError);
51
53
  const { uri } = parseFlagOptions(extra, 'query', OWN_FLAGS, onError);
52
- return { serverCommand, serverArgs, cwd, logLevel, uri: assertRequired(uri, '--uri', 'query', onError) };
54
+ return { serverCommand, serverArgs, cwd, logLevel, logFile, logFileLevel, uri: assertRequired(uri, '--uri', 'query', onError) };
53
55
  }
54
56
 
55
57
  export function runQueryCommand(args: string[]): Promise<void> {