@aster-cloud/aster-lang-ts 1.0.29 → 1.0.31

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 (291) hide show
  1. package/dist/scripts/aster.js +11 -26
  2. package/dist/scripts/aster.js.map +1 -1
  3. package/dist/scripts/corpus-loader.d.ts +17 -0
  4. package/dist/scripts/corpus-loader.d.ts.map +1 -0
  5. package/dist/scripts/corpus-loader.js +60 -0
  6. package/dist/scripts/corpus-loader.js.map +1 -0
  7. package/dist/scripts/emit-classfiles-core.js +5 -13
  8. package/dist/scripts/emit-classfiles-core.js.map +1 -1
  9. package/dist/scripts/emit-classfiles.js +7 -12
  10. package/dist/scripts/emit-classfiles.js.map +1 -1
  11. package/dist/scripts/generate_error_codes.js +2 -0
  12. package/dist/scripts/generate_error_codes.js.map +1 -1
  13. package/dist/scripts/golden.js +4 -1
  14. package/dist/scripts/golden.js.map +1 -1
  15. package/dist/scripts/test-lossless-golden.js +2 -1
  16. package/dist/scripts/test-lossless-golden.js.map +1 -1
  17. package/dist/scripts/validate_error_codes.js +1 -0
  18. package/dist/scripts/validate_error_codes.js.map +1 -1
  19. package/dist/scripts/verify-lexicon-sync.js +5 -1
  20. package/dist/scripts/verify-lexicon-sync.js.map +1 -1
  21. package/dist/src/ast/ast.d.ts +1 -1
  22. package/dist/src/ast/ast.d.ts.map +1 -1
  23. package/dist/src/ast/ast.js +2 -1
  24. package/dist/src/ast/ast.js.map +1 -1
  25. package/dist/src/browser.d.ts +7 -0
  26. package/dist/src/browser.d.ts.map +1 -1
  27. package/dist/src/browser.js +4 -0
  28. package/dist/src/browser.js.map +1 -1
  29. package/dist/src/cli/utils/gradle-env.d.ts +9 -0
  30. package/dist/src/cli/utils/gradle-env.d.ts.map +1 -0
  31. package/dist/src/cli/utils/gradle-env.js +18 -0
  32. package/dist/src/cli/utils/gradle-env.js.map +1 -0
  33. package/dist/src/cli/utils/out-dir.d.ts +18 -0
  34. package/dist/src/cli/utils/out-dir.d.ts.map +1 -0
  35. package/dist/src/cli/utils/out-dir.js +49 -0
  36. package/dist/src/cli/utils/out-dir.js.map +1 -0
  37. package/dist/src/cnl-printer.d.ts +10 -0
  38. package/dist/src/cnl-printer.d.ts.map +1 -0
  39. package/dist/src/cnl-printer.js +360 -0
  40. package/dist/src/cnl-printer.js.map +1 -0
  41. package/dist/src/config/lexicons/de-DE.d.ts.map +1 -1
  42. package/dist/src/config/lexicons/de-DE.js +8 -2
  43. package/dist/src/config/lexicons/de-DE.js.map +1 -1
  44. package/dist/src/config/lexicons/en-US.d.ts.map +1 -1
  45. package/dist/src/config/lexicons/en-US.js +8 -4
  46. package/dist/src/config/lexicons/en-US.js.map +1 -1
  47. package/dist/src/config/lexicons/hi-IN.d.ts.map +1 -1
  48. package/dist/src/config/lexicons/hi-IN.js +8 -2
  49. package/dist/src/config/lexicons/hi-IN.js.map +1 -1
  50. package/dist/src/config/lexicons/template.d.ts.map +1 -1
  51. package/dist/src/config/lexicons/template.js +12 -0
  52. package/dist/src/config/lexicons/template.js.map +1 -1
  53. package/dist/src/config/lexicons/zh-CN.d.ts.map +1 -1
  54. package/dist/src/config/lexicons/zh-CN.js +9 -3
  55. package/dist/src/config/lexicons/zh-CN.js.map +1 -1
  56. package/dist/src/config/semantic.d.ts +6 -0
  57. package/dist/src/config/semantic.d.ts.map +1 -1
  58. package/dist/src/config/semantic.js +8 -0
  59. package/dist/src/config/semantic.js.map +1 -1
  60. package/dist/src/config/token-kind.d.ts +12 -0
  61. package/dist/src/config/token-kind.d.ts.map +1 -1
  62. package/dist/src/config/token-kind.js +18 -0
  63. package/dist/src/config/token-kind.js.map +1 -1
  64. package/dist/src/core/core_ir.d.ts +1 -1
  65. package/dist/src/core/core_ir.d.ts.map +1 -1
  66. package/dist/src/core/core_ir.js +3 -1
  67. package/dist/src/core/core_ir.js.map +1 -1
  68. package/dist/src/core/interpreter.d.ts.map +1 -1
  69. package/dist/src/core/interpreter.js +222 -18
  70. package/dist/src/core/interpreter.js.map +1 -1
  71. package/dist/src/cst/cst_printer.d.ts.map +1 -1
  72. package/dist/src/cst/cst_printer.js +66 -32
  73. package/dist/src/cst/cst_printer.js.map +1 -1
  74. package/dist/src/diagnostics/diagnostics.d.ts +1 -0
  75. package/dist/src/diagnostics/diagnostics.d.ts.map +1 -1
  76. package/dist/src/diagnostics/diagnostics.js +1 -0
  77. package/dist/src/diagnostics/diagnostics.js.map +1 -1
  78. package/dist/src/diagnostics/error_codes.d.ts +10 -2
  79. package/dist/src/diagnostics/error_codes.d.ts.map +1 -1
  80. package/dist/src/diagnostics/error_codes.js +64 -0
  81. package/dist/src/diagnostics/error_codes.js.map +1 -1
  82. package/dist/src/effects/effect_inference.js +1 -1
  83. package/dist/src/effects/effect_inference.js.map +1 -1
  84. package/dist/src/formatter.d.ts +3 -0
  85. package/dist/src/formatter.d.ts.map +1 -1
  86. package/dist/src/formatter.js +8 -261
  87. package/dist/src/formatter.js.map +1 -1
  88. package/dist/src/frontend/transformers.d.ts.map +1 -1
  89. package/dist/src/frontend/transformers.js +10 -2
  90. package/dist/src/frontend/transformers.js.map +1 -1
  91. package/dist/src/governance/controls-registry.data.d.ts +40 -0
  92. package/dist/src/governance/controls-registry.data.d.ts.map +1 -0
  93. package/dist/src/governance/controls-registry.data.js +35 -0
  94. package/dist/src/governance/controls-registry.data.js.map +1 -0
  95. package/dist/src/governance/controls.d.ts +23 -0
  96. package/dist/src/governance/controls.d.ts.map +1 -0
  97. package/dist/src/governance/controls.js +77 -0
  98. package/dist/src/governance/controls.js.map +1 -0
  99. package/dist/src/index.d.ts +4 -0
  100. package/dist/src/index.d.ts.map +1 -1
  101. package/dist/src/index.js +2 -0
  102. package/dist/src/index.js.map +1 -1
  103. package/dist/src/lower_to_core.js +1 -1
  104. package/dist/src/lower_to_core.js.map +1 -1
  105. package/dist/src/lsp/completion.d.ts +22 -1
  106. package/dist/src/lsp/completion.d.ts.map +1 -1
  107. package/dist/src/lsp/completion.js +42 -1
  108. package/dist/src/lsp/completion.js.map +1 -1
  109. package/dist/src/lsp/debounce-map.d.ts +16 -0
  110. package/dist/src/lsp/debounce-map.d.ts.map +1 -0
  111. package/dist/src/lsp/debounce-map.js +32 -0
  112. package/dist/src/lsp/debounce-map.js.map +1 -0
  113. package/dist/src/lsp/server.js +6 -8
  114. package/dist/src/lsp/server.js.map +1 -1
  115. package/dist/src/lsp/utils.d.ts.map +1 -1
  116. package/dist/src/lsp/utils.js +2 -0
  117. package/dist/src/lsp/utils.js.map +1 -1
  118. package/dist/src/lsp/workspace/file-watcher.d.ts +1 -0
  119. package/dist/src/lsp/workspace/file-watcher.d.ts.map +1 -1
  120. package/dist/src/lsp/workspace/file-watcher.js +24 -14
  121. package/dist/src/lsp/workspace/file-watcher.js.map +1 -1
  122. package/dist/src/manifest.d.ts +2 -0
  123. package/dist/src/manifest.d.ts.map +1 -1
  124. package/dist/src/manifest.js.map +1 -1
  125. package/dist/src/package/manifest-parser.d.ts +10 -0
  126. package/dist/src/package/manifest-parser.d.ts.map +1 -1
  127. package/dist/src/package/manifest-parser.js +27 -28
  128. package/dist/src/package/manifest-parser.js.map +1 -1
  129. package/dist/src/package/manifest-schema.d.ts +15 -0
  130. package/dist/src/package/manifest-schema.d.ts.map +1 -0
  131. package/dist/src/package/manifest-schema.js +116 -0
  132. package/dist/src/package/manifest-schema.js.map +1 -0
  133. package/dist/src/parser/context.d.ts +2 -0
  134. package/dist/src/parser/context.d.ts.map +1 -1
  135. package/dist/src/parser/context.js +1 -0
  136. package/dist/src/parser/context.js.map +1 -1
  137. package/dist/src/parser/decl-parser.d.ts.map +1 -1
  138. package/dist/src/parser/decl-parser.js +26 -10
  139. package/dist/src/parser/decl-parser.js.map +1 -1
  140. package/dist/src/parser/expr-stmt-parser.d.ts +4 -1
  141. package/dist/src/parser/expr-stmt-parser.d.ts.map +1 -1
  142. package/dist/src/parser/expr-stmt-parser.js +147 -6
  143. package/dist/src/parser/expr-stmt-parser.js.map +1 -1
  144. package/dist/src/parser/import-parser.d.ts +12 -0
  145. package/dist/src/parser/import-parser.d.ts.map +1 -1
  146. package/dist/src/parser/import-parser.js +28 -0
  147. package/dist/src/parser/import-parser.js.map +1 -1
  148. package/dist/src/parser.js +1 -1
  149. package/dist/src/parser.js.map +1 -1
  150. package/dist/src/typecheck/browser.d.ts +3 -0
  151. package/dist/src/typecheck/browser.d.ts.map +1 -1
  152. package/dist/src/typecheck/browser.js +10 -1
  153. package/dist/src/typecheck/browser.js.map +1 -1
  154. package/dist/src/typecheck/context.d.ts +3 -0
  155. package/dist/src/typecheck/context.d.ts.map +1 -1
  156. package/dist/src/typecheck/context.js.map +1 -1
  157. package/dist/src/typecheck/expression.d.ts +6 -0
  158. package/dist/src/typecheck/expression.d.ts.map +1 -1
  159. package/dist/src/typecheck/expression.js +54 -2
  160. package/dist/src/typecheck/expression.js.map +1 -1
  161. package/dist/src/typecheck/generics.d.ts.map +1 -1
  162. package/dist/src/typecheck/generics.js +3 -0
  163. package/dist/src/typecheck/generics.js.map +1 -1
  164. package/dist/src/typecheck/governance.d.ts +43 -0
  165. package/dist/src/typecheck/governance.d.ts.map +1 -0
  166. package/dist/src/typecheck/governance.js +162 -0
  167. package/dist/src/typecheck/governance.js.map +1 -0
  168. package/dist/src/typecheck/module.d.ts.map +1 -1
  169. package/dist/src/typecheck/module.js +10 -1
  170. package/dist/src/typecheck/module.js.map +1 -1
  171. package/dist/src/typecheck/statement.d.ts.map +1 -1
  172. package/dist/src/typecheck/statement.js +2 -2
  173. package/dist/src/typecheck/statement.js.map +1 -1
  174. package/dist/src/typecheck/type_system.d.ts.map +1 -1
  175. package/dist/src/typecheck/type_system.js +4 -0
  176. package/dist/src/typecheck/type_system.js.map +1 -1
  177. package/dist/src/typecheck/verdict_signatures.d.ts +19 -0
  178. package/dist/src/typecheck/verdict_signatures.d.ts.map +1 -0
  179. package/dist/src/typecheck/verdict_signatures.js +23 -0
  180. package/dist/src/typecheck/verdict_signatures.js.map +1 -0
  181. package/dist/src/types/base.d.ts +2 -0
  182. package/dist/src/types/base.d.ts.map +1 -1
  183. package/dist/test/helpers/sibling-source.d.ts +10 -0
  184. package/dist/test/helpers/sibling-source.d.ts.map +1 -0
  185. package/dist/test/helpers/sibling-source.js +20 -0
  186. package/dist/test/helpers/sibling-source.js.map +1 -0
  187. package/dist/test/unit/allocation-budget.test.d.ts +2 -0
  188. package/dist/test/unit/allocation-budget.test.d.ts.map +1 -0
  189. package/dist/test/unit/allocation-budget.test.js +160 -0
  190. package/dist/test/unit/allocation-budget.test.js.map +1 -0
  191. package/dist/test/unit/apply-call.test.js +5 -0
  192. package/dist/test/unit/apply-call.test.js.map +1 -1
  193. package/dist/test/unit/canonicalizer/possessive-anchor.test.js +10 -0
  194. package/dist/test/unit/canonicalizer/possessive-anchor.test.js.map +1 -1
  195. package/dist/test/unit/cli/gradle-env-guard.test.d.ts +2 -0
  196. package/dist/test/unit/cli/gradle-env-guard.test.d.ts.map +1 -0
  197. package/dist/test/unit/cli/gradle-env-guard.test.js +53 -0
  198. package/dist/test/unit/cli/gradle-env-guard.test.js.map +1 -0
  199. package/dist/test/unit/cli/gradle-env.test.d.ts +2 -0
  200. package/dist/test/unit/cli/gradle-env.test.d.ts.map +1 -0
  201. package/dist/test/unit/cli/gradle-env.test.js +31 -0
  202. package/dist/test/unit/cli/gradle-env.test.js.map +1 -0
  203. package/dist/test/unit/cli/out-dir.test.d.ts +2 -0
  204. package/dist/test/unit/cli/out-dir.test.d.ts.map +1 -0
  205. package/dist/test/unit/cli/out-dir.test.js +96 -0
  206. package/dist/test/unit/cli/out-dir.test.js.map +1 -0
  207. package/dist/test/unit/formatter-corpus-roundtrip.test.d.ts +2 -0
  208. package/dist/test/unit/formatter-corpus-roundtrip.test.d.ts.map +1 -0
  209. package/dist/test/unit/formatter-corpus-roundtrip.test.js +190 -0
  210. package/dist/test/unit/formatter-corpus-roundtrip.test.js.map +1 -0
  211. package/dist/test/unit/formatter-roundtrip.test.d.ts +2 -0
  212. package/dist/test/unit/formatter-roundtrip.test.d.ts.map +1 -0
  213. package/dist/test/unit/formatter-roundtrip.test.js +125 -0
  214. package/dist/test/unit/formatter-roundtrip.test.js.map +1 -0
  215. package/dist/test/unit/governance/controls-registry-parity.test.d.ts +2 -0
  216. package/dist/test/unit/governance/controls-registry-parity.test.d.ts.map +1 -0
  217. package/dist/test/unit/governance/controls-registry-parity.test.js +28 -0
  218. package/dist/test/unit/governance/controls-registry-parity.test.js.map +1 -0
  219. package/dist/test/unit/governance/controls-registry-profiles.test.d.ts +2 -0
  220. package/dist/test/unit/governance/controls-registry-profiles.test.d.ts.map +1 -0
  221. package/dist/test/unit/governance/controls-registry-profiles.test.js +106 -0
  222. package/dist/test/unit/governance/controls-registry-profiles.test.js.map +1 -0
  223. package/dist/test/unit/governance/governance-check.test.d.ts +2 -0
  224. package/dist/test/unit/governance/governance-check.test.d.ts.map +1 -0
  225. package/dist/test/unit/governance/governance-check.test.js +169 -0
  226. package/dist/test/unit/governance/governance-check.test.js.map +1 -0
  227. package/dist/test/unit/governance/profile-check.test.d.ts +2 -0
  228. package/dist/test/unit/governance/profile-check.test.d.ts.map +1 -0
  229. package/dist/test/unit/governance/profile-check.test.js +139 -0
  230. package/dist/test/unit/governance/profile-check.test.js.map +1 -0
  231. package/dist/test/unit/governance/verdict-typecheck.test.d.ts +2 -0
  232. package/dist/test/unit/governance/verdict-typecheck.test.d.ts.map +1 -0
  233. package/dist/test/unit/governance/verdict-typecheck.test.js +80 -0
  234. package/dist/test/unit/governance/verdict-typecheck.test.js.map +1 -0
  235. package/dist/test/unit/interpreter/verdict-builtins.test.d.ts +2 -0
  236. package/dist/test/unit/interpreter/verdict-builtins.test.d.ts.map +1 -0
  237. package/dist/test/unit/interpreter/verdict-builtins.test.js +72 -0
  238. package/dist/test/unit/interpreter/verdict-builtins.test.js.map +1 -0
  239. package/dist/test/unit/list-numeric-fail-loud.test.d.ts +2 -0
  240. package/dist/test/unit/list-numeric-fail-loud.test.d.ts.map +1 -0
  241. package/dist/test/unit/list-numeric-fail-loud.test.js +83 -0
  242. package/dist/test/unit/list-numeric-fail-loud.test.js.map +1 -0
  243. package/dist/test/unit/lossless-mirror.test.d.ts +2 -0
  244. package/dist/test/unit/lossless-mirror.test.d.ts.map +1 -0
  245. package/dist/test/unit/lossless-mirror.test.js +41 -0
  246. package/dist/test/unit/lossless-mirror.test.js.map +1 -0
  247. package/dist/test/unit/lossless-reflow.test.d.ts +2 -0
  248. package/dist/test/unit/lossless-reflow.test.d.ts.map +1 -0
  249. package/dist/test/unit/lossless-reflow.test.js +84 -0
  250. package/dist/test/unit/lossless-reflow.test.js.map +1 -0
  251. package/dist/test/unit/lowering/lowering.test.js +35 -35
  252. package/dist/test/unit/lowering/lowering.test.js.map +1 -1
  253. package/dist/test/unit/lsp/control-completion.test.d.ts +2 -0
  254. package/dist/test/unit/lsp/control-completion.test.d.ts.map +1 -0
  255. package/dist/test/unit/lsp/control-completion.test.js +46 -0
  256. package/dist/test/unit/lsp/control-completion.test.js.map +1 -0
  257. package/dist/test/unit/lsp/debounce-map.test.d.ts +2 -0
  258. package/dist/test/unit/lsp/debounce-map.test.d.ts.map +1 -0
  259. package/dist/test/unit/lsp/debounce-map.test.js +47 -0
  260. package/dist/test/unit/lsp/debounce-map.test.js.map +1 -0
  261. package/dist/test/unit/lsp/file-watcher-restart.test.d.ts +2 -0
  262. package/dist/test/unit/lsp/file-watcher-restart.test.d.ts.map +1 -0
  263. package/dist/test/unit/lsp/file-watcher-restart.test.js +40 -0
  264. package/dist/test/unit/lsp/file-watcher-restart.test.js.map +1 -0
  265. package/dist/test/unit/manifest-parser.test.js +8 -0
  266. package/dist/test/unit/manifest-parser.test.js.map +1 -1
  267. package/dist/test/unit/manifest-schema.test.d.ts +7 -5
  268. package/dist/test/unit/manifest-schema.test.d.ts.map +1 -1
  269. package/dist/test/unit/manifest-schema.test.js +48 -10
  270. package/dist/test/unit/manifest-schema.test.js.map +1 -1
  271. package/dist/test/unit/parser/governance-sugar.test.d.ts +2 -0
  272. package/dist/test/unit/parser/governance-sugar.test.d.ts.map +1 -0
  273. package/dist/test/unit/parser/governance-sugar.test.js +258 -0
  274. package/dist/test/unit/parser/governance-sugar.test.js.map +1 -0
  275. package/dist/test/unit/parser/module-header.test.d.ts +2 -0
  276. package/dist/test/unit/parser/module-header.test.d.ts.map +1 -0
  277. package/dist/test/unit/parser/module-header.test.js +25 -0
  278. package/dist/test/unit/parser/module-header.test.js.map +1 -0
  279. package/dist/test/unit/parser/positional-annotation-args.test.d.ts +2 -0
  280. package/dist/test/unit/parser/positional-annotation-args.test.d.ts.map +1 -0
  281. package/dist/test/unit/parser/positional-annotation-args.test.js +26 -0
  282. package/dist/test/unit/parser/positional-annotation-args.test.js.map +1 -0
  283. package/dist/test/unit/parser/prefix-operator-call.test.d.ts +2 -0
  284. package/dist/test/unit/parser/prefix-operator-call.test.d.ts.map +1 -0
  285. package/dist/test/unit/parser/prefix-operator-call.test.js +69 -0
  286. package/dist/test/unit/parser/prefix-operator-call.test.js.map +1 -0
  287. package/dist/test/unit/scripts/corpus-loader.test.d.ts +2 -0
  288. package/dist/test/unit/scripts/corpus-loader.test.d.ts.map +1 -0
  289. package/dist/test/unit/scripts/corpus-loader.test.js +85 -0
  290. package/dist/test/unit/scripts/corpus-loader.test.js.map +1 -0
  291. package/package.json +1 -1
@@ -0,0 +1,190 @@
1
+ /**
2
+ * 全语料格式化往返:本仓与兄弟仓 aster-lang-test/corpus 下每个能编译的 .aster,
3
+ * 格式化后重新编译,Core IR 须与原文相同(忽略 origin)。
4
+ *
5
+ * 源文的词法包取 .meta.json 的 lexicon,否则依次尝试 en-US / zh-CN / de-DE,取第一个能编译的;
6
+ * 哪个都编译不了的(错误夹具、旧语法示例)不在往返范围内。格式化器输出英文 CNL,故一律用 en-US 重新编译。
7
+ *
8
+ * 另对同一语料跑 LSP 默认格式化(lossless + reflow):再跑一次结果不变,字符串、注释、缩进与句点不变,
9
+ * 不留行尾空白,CRLF 版本的结果即 LF 结果换成 CRLF;能编译的文件以原词法包重新编译 Core IR 不变
10
+ * (reflow 不翻译,保留源文语言)。
11
+ */
12
+ import { test } from 'node:test';
13
+ import assert from 'node:assert/strict';
14
+ import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
15
+ import { dirname, join, relative } from 'node:path';
16
+ import { fileURLToPath } from 'node:url';
17
+ import { canonicalize } from '../../src/frontend/canonicalizer.js';
18
+ import { lex } from '../../src/frontend/lexer.js';
19
+ import { parseWithLexicon } from '../../src/parser.js';
20
+ import { lowerModule } from '../../src/lower_to_core.js';
21
+ import { formatCNL } from '../../src/formatter.js';
22
+ import { buildCstLossless } from '../../src/cst/cst_builder.js';
23
+ import { printCNLFromCst } from '../../src/cst/cst_printer.js';
24
+ import { EN_US } from '../../src/config/lexicons/en-US.js';
25
+ import { ZH_CN } from '../../src/config/lexicons/zh-CN.js';
26
+ import { DE_DE } from '../../src/config/lexicons/de-DE.js';
27
+ // 编译后从 dist/test/unit 运行:上溯 3 级到仓库根
28
+ const repoRoot = join(dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
29
+ const SKIP_DIRS = new Set(['node_modules', 'dist', 'coverage', '.git', '.ccg', 'aster-lang-test']);
30
+ const LEXICONS = { 'en-US': EN_US, 'zh-CN': ZH_CN, 'de-DE': DE_DE };
31
+ // 源文用中文标识符:格式化器只输出英文 CNL,而 en-US 词法不接受 CJK 标识符字符(lexer isLetter 英文模式),
32
+ // 英文重写后无法重新词法分析。路径相对兄弟仓 aster-lang-test 根。
33
+ const CJK_IDENTIFIERS = '中文标识符无法以英文 CNL 重写(en-US 词法不接受 CJK 标识符)';
34
+ const ALLOW_LIST = new Map([
35
+ ['corpus/conformance/cjk-v2/01-punctuation-basic.aster', CJK_IDENTIFIERS],
36
+ ['corpus/conformance/cjk-v2/02-string-preservation.aster', CJK_IDENTIFIERS],
37
+ ['corpus/conformance/cjk-v2/04-identifier-no-collision.aster', CJK_IDENTIFIERS],
38
+ ['corpus/tier3-fixtures/lexicon-i18n/01-hello__i18n-zh-CN.aster', CJK_IDENTIFIERS],
39
+ ['corpus/tier3-fixtures/lexicon-i18n/02-types__i18n-zh-CN.aster', CJK_IDENTIFIERS],
40
+ ['corpus/tier3-fixtures/lexicon-i18n/03-functions__i18n-zh-CN.aster', CJK_IDENTIFIERS],
41
+ ['corpus/tier3-fixtures/lexicon-i18n/04-control-flow__i18n-zh-CN.aster', CJK_IDENTIFIERS],
42
+ ['corpus/tier3-fixtures/lexicon-i18n/05-patterns__i18n-zh-CN.aster', CJK_IDENTIFIERS],
43
+ ['corpus/tier3-fixtures/lexicon-i18n/06-operators__i18n-zh-CN.aster', CJK_IDENTIFIERS],
44
+ ['corpus/tier3-fixtures/lexicon-i18n/user_greeting.aster', CJK_IDENTIFIERS],
45
+ ]);
46
+ function asterFiles(dir, out = []) {
47
+ for (const entry of readdirSync(dir)) {
48
+ if (SKIP_DIRS.has(entry))
49
+ continue;
50
+ const path = join(dir, entry);
51
+ if (statSync(path).isDirectory())
52
+ asterFiles(path, out);
53
+ else if (path.endsWith('.aster'))
54
+ out.push(path);
55
+ }
56
+ return out;
57
+ }
58
+ function siblingTestRepo() {
59
+ return [join(repoRoot, '..', 'aster-lang-test'), join(repoRoot, 'aster-lang-test')]
60
+ .find((c) => existsSync(join(c, 'corpus')));
61
+ }
62
+ function toCore(source, lexicon) {
63
+ const result = parseWithLexicon(lex(canonicalize(source, lexicon), lexicon), lexicon);
64
+ const errors = result.diagnostics.filter((d) => d.severity === 'error');
65
+ if (errors.length > 0)
66
+ throw new Error(errors[0].message);
67
+ return lowerModule(result.ast);
68
+ }
69
+ function stripOrigins(o) {
70
+ if (Array.isArray(o))
71
+ return o.map(stripOrigins);
72
+ if (!o || typeof o !== 'object')
73
+ return o;
74
+ return Object.fromEntries(Object.entries(o).filter(([k]) => k !== 'origin').map(([k, v]) => [k, stripOrigins(v)]));
75
+ }
76
+ function declaredLexicon(file) {
77
+ const meta = file.replace(/\.aster$/, '.meta.json');
78
+ return existsSync(meta) ? JSON.parse(readFileSync(meta, 'utf8')).lexicon : undefined;
79
+ }
80
+ /** 返回能编译源文的词法包及其 Core IR;都不能编译时为 undefined */
81
+ function compileWithAnyLexicon(file, source) {
82
+ const names = [declaredLexicon(file), 'en-US', 'zh-CN', 'de-DE'].filter((n) => !!n && n in LEXICONS);
83
+ for (const name of names) {
84
+ try {
85
+ return { lexicon: LEXICONS[name], core: stripOrigins(toCore(source, LEXICONS[name])) };
86
+ }
87
+ catch {
88
+ // 换下一个词法包
89
+ }
90
+ }
91
+ return undefined;
92
+ }
93
+ /** 格式化后重新编译与原文比对;返回失败原因,成功为 undefined */
94
+ function corpusFiles(t) {
95
+ const sibling = siblingTestRepo();
96
+ if (sibling === undefined) {
97
+ assert.ok(!process.env.CI, 'CI 中须 checkout aster-lang-test(见 .github/workflows/ci.yml test job)');
98
+ t.diagnostic('aster-lang-test 未并列 checkout,只检查本仓语料');
99
+ }
100
+ return [
101
+ ...asterFiles(repoRoot).map((f) => ({ file: f, key: relative(repoRoot, f) })),
102
+ ...(sibling ? asterFiles(join(sibling, 'corpus')).map((f) => ({ file: f, key: relative(sibling, f) })) : []),
103
+ ];
104
+ }
105
+ /** 无法建 lossless CST(词法错误)时 LSP 不给出编辑,此处同样返回 undefined */
106
+ function losslessCst(source) {
107
+ try {
108
+ return buildCstLossless(source);
109
+ }
110
+ catch {
111
+ return undefined;
112
+ }
113
+ }
114
+ /**
115
+ * reflow 不得改动的部分:除换行外的记号(字符串字面量、缩进 INDENT/DEDENT、句点等)与注释正文(行尾空白除外)。
116
+ * 唯一允许的记号改动是 `.` 与紧随其后的 `:` 合并,故比较前去掉这种 `.`。
117
+ */
118
+ function untouchable(cst) {
119
+ const merged = (i) => cst.tokens[i].lexeme === '.' && cst.tokens[i + 1]?.lexeme === ':';
120
+ const kept = cst.tokens
121
+ .filter((tk, i) => tk.kind !== 'NEWLINE' && tk.kind !== 'EOF' && !merged(i))
122
+ .map((tk) => `${tk.kind}:${tk.lexeme}`);
123
+ const comments = (cst.inlineComments ?? []).map((c) => c.text.trimEnd());
124
+ return JSON.stringify([kept, comments]);
125
+ }
126
+ /** lossless reflow 后检查幂等、不可改动部分与 Core IR;返回失败原因,成功或不适用为 undefined */
127
+ function reflowProblem(file) {
128
+ const source = readFileSync(file, 'utf8');
129
+ const cst = losslessCst(source);
130
+ if (cst === undefined)
131
+ return undefined;
132
+ const once = printCNLFromCst(cst, { reflow: true });
133
+ const onceCst = losslessCst(once);
134
+ if (onceCst === undefined)
135
+ return 'reflow 结果无法重新词法分析';
136
+ if (printCNLFromCst(onceCst, { reflow: true }) !== once)
137
+ return '二次 reflow 结果不同';
138
+ if (untouchable(onceCst) !== untouchable(cst))
139
+ return '字符串、注释、缩进或句点被改动';
140
+ if (once.split('\n').some((line) => /[ \t]\r?$/.test(line)))
141
+ return '仍有行尾空白';
142
+ const crlf = losslessCst(source.replace(/\r?\n/g, '\r\n'));
143
+ if (crlf === undefined || printCNLFromCst(crlf, { reflow: true }) !== once.replace(/\r?\n/g, '\r\n')) {
144
+ return 'CRLF 版本的 reflow 结果与 LF 版本不一致';
145
+ }
146
+ const compiled = compileWithAnyLexicon(file, source);
147
+ if (compiled === undefined)
148
+ return undefined;
149
+ try {
150
+ assert.deepEqual(stripOrigins(toCore(once, compiled.lexicon)), compiled.core);
151
+ return undefined;
152
+ }
153
+ catch (e) {
154
+ return e.message.split('\n')[0];
155
+ }
156
+ }
157
+ function roundTripProblem(file) {
158
+ const source = readFileSync(file, 'utf8');
159
+ const compiled = compileWithAnyLexicon(file, source);
160
+ if (compiled === undefined)
161
+ return undefined;
162
+ const formatted = formatCNL(source, { lexicon: compiled.lexicon });
163
+ try {
164
+ assert.deepEqual(stripOrigins(toCore(formatted, EN_US)), compiled.core);
165
+ return undefined;
166
+ }
167
+ catch (e) {
168
+ return e.message.split('\n')[0];
169
+ }
170
+ }
171
+ test('全语料格式化往返 Core IR 不变', (t) => {
172
+ const failures = corpusFiles(t)
173
+ .map(({ file, key }) => ({ key, problem: roundTripProblem(file) }))
174
+ .filter(({ key, problem }) => problem !== undefined && !ALLOW_LIST.has(key));
175
+ assert.deepEqual(failures, []);
176
+ });
177
+ test('全语料 lossless reflow:幂等,不改字符串、注释、缩进与句点,Core IR 不变', (t) => {
178
+ const failures = corpusFiles(t)
179
+ .map(({ file, key }) => ({ key, problem: reflowProblem(file) }))
180
+ .filter(({ problem }) => problem !== undefined);
181
+ assert.deepEqual(failures, []);
182
+ });
183
+ test('允许清单中的条目确实仍不能往返(能往返的须移出清单)', (t) => {
184
+ const sibling = siblingTestRepo();
185
+ if (sibling === undefined)
186
+ return t.skip('aster-lang-test 未并列 checkout');
187
+ const stale = [...ALLOW_LIST.keys()].filter((key) => roundTripProblem(join(sibling, key)) === undefined);
188
+ assert.deepEqual(stale, []);
189
+ });
190
+ //# sourceMappingURL=formatter-corpus-roundtrip.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter-corpus-roundtrip.test.js","sourceRoot":"","sources":["../../../test/unit/formatter-corpus-roundtrip.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=formatter-roundtrip.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter-roundtrip.test.d.ts","sourceRoot":"","sources":["../../../test/unit/formatter-roundtrip.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,125 @@
1
+ /**
2
+ * 格式化器往返:格式化输出须能重新编译,且 Core IR 与原文相同(去掉 origin 后)。
3
+ *
4
+ * 夹具取自 aster-lang-test 的语法糖/长写法样本与 aster-cloud 的信贷试点 v3(en/zh/de)。
5
+ * 格式化器一律输出英文 CNL,语法糖按长写法输出(ADR 0046 §5),故重新编译统一用 en-US。
6
+ */
7
+ import { describe, test } from 'node:test';
8
+ import assert from 'node:assert/strict';
9
+ import { readFileSync } from 'node:fs';
10
+ import { dirname, join } from 'node:path';
11
+ import { fileURLToPath } from 'node:url';
12
+ import { canonicalize } from '../../src/frontend/canonicalizer.js';
13
+ import { lex } from '../../src/frontend/lexer.js';
14
+ import { parseWithLexicon } from '../../src/parser.js';
15
+ import { lowerModule } from '../../src/lower_to_core.js';
16
+ import { formatCNL } from '../../src/formatter.js';
17
+ import { EN_US } from '../../src/config/lexicons/en-US.js';
18
+ import { ZH_CN } from '../../src/config/lexicons/zh-CN.js';
19
+ import { DE_DE } from '../../src/config/lexicons/de-DE.js';
20
+ // 编译后从 dist/test/unit 运行:上溯 3 级到仓库根,夹具在 test/fixtures 下
21
+ const repoRoot = join(dirname(fileURLToPath(import.meta.url)), '..', '..', '..');
22
+ const fixtureDir = join(repoRoot, 'test', 'fixtures', 'formatter-roundtrip');
23
+ function toCore(source, lexicon = EN_US) {
24
+ const tokens = lex(canonicalize(source, lexicon), lexicon);
25
+ const result = parseWithLexicon(tokens, lexicon);
26
+ const errors = result.diagnostics.filter((d) => d.severity === 'error');
27
+ if (errors.length > 0)
28
+ throw new Error(errors.map((d) => d.message).join('\n') + '\n---\n' + source);
29
+ return lowerModule(result.ast);
30
+ }
31
+ function stripOrigins(o) {
32
+ if (Array.isArray(o))
33
+ return o.map(stripOrigins);
34
+ if (!o || typeof o !== 'object')
35
+ return o;
36
+ const out = {};
37
+ for (const [k, v] of Object.entries(o)) {
38
+ if (k !== 'origin')
39
+ out[k] = stripOrigins(v);
40
+ }
41
+ return out;
42
+ }
43
+ // 格式化 → 用 en-US 重新编译 → 与原文 IR 比对;返回格式化输出供进一步断言
44
+ function assertRoundTrip(source, lexicon = EN_US) {
45
+ const formatted = formatCNL(source, { lexicon });
46
+ assert.deepEqual(stripOrigins(toCore(formatted)), stripOrigins(toCore(source, lexicon)), formatted);
47
+ return formatted;
48
+ }
49
+ const FIXTURES = [
50
+ ['governance-sugar.aster', EN_US],
51
+ ['governance-sugar-long.aster', EN_US],
52
+ ['credit-pilot-v3.en.aster', EN_US],
53
+ ['credit-pilot-v3.zh.aster', ZH_CN],
54
+ ['credit-pilot-v3.de.aster', DE_DE],
55
+ ];
56
+ describe('格式化器往返(Core IR 不变)', () => {
57
+ for (const [file, lexicon] of FIXTURES) {
58
+ test(file, () => {
59
+ const formatted = assertRoundTrip(readFileSync(join(fixtureDir, file), 'utf8'), lexicon);
60
+ assert.doesNotMatch(formatted, /,:/);
61
+ assert.doesNotMatch(formatted, /(>=|<=|[<>*+]|\band)\(/);
62
+ assert.equal(formatCNL(formatted), formatted, '格式化须幂等');
63
+ });
64
+ }
65
+ test('If 与 Otherwise 块头不带逗号', () => {
66
+ const src = ['Module m.', '', 'Rule r given n as Int, produce Int:', ' If n at least 1:',
67
+ ' Return 1.', ' Otherwise:', ' Return 0.', ''].join('\n');
68
+ const formatted = assertRoundTrip(src);
69
+ assert.match(formatted, /\n {2}If n at least 1:\n/);
70
+ assert.match(formatted, /\n {2}Otherwise:\n/);
71
+ });
72
+ test('数值字面量极值按普通十进制输出并原值往返', () => {
73
+ const literals = [
74
+ // [源文写法, 返回类型, 期望 Core 字面量值]
75
+ ['0.0000001', 'Double', 1e-7],
76
+ ['123456789012345678901234.5', 'Double', 123456789012345678901234.5],
77
+ ['0.5', 'Double', 0.5],
78
+ ['3.0', 'Double', 3],
79
+ ['2147483647', 'Int', 2147483647],
80
+ ['0', 'Int', 0],
81
+ ['9223372036854775807L', 'Long', '9223372036854775807'],
82
+ ];
83
+ for (const [literal, ret, value] of literals) {
84
+ const src = `Module m.\n\nRule r, produce ${ret}:\n Return ${literal}.\n`;
85
+ const formatted = assertRoundTrip(src);
86
+ assert.doesNotMatch(formatted, /\d[eE][+-]?\d/, formatted);
87
+ const ret0 = toCore(formatted).decls[0].body.statements[0];
88
+ assert.equal(ret0.expr.value, value, literal);
89
+ }
90
+ });
91
+ test('构造字段以逗号分隔,只在会贪婪吞并后续字段时加括号', () => {
92
+ const src = ['Module m.', '', 'Define Inner has x as Int, y as Int.', '',
93
+ 'Define Outer has inner as Inner, wrapped as Option of Inner, n as Int, ok as Bool.', '',
94
+ 'Rule r given k as Int, produce Outer:',
95
+ ' Return Outer with inner set to (Inner with x set to 1, y set to 2), ' +
96
+ 'wrapped set to some of (Inner with x set to k plus 1, y set to 4), n set to k plus 1, ok set to k at least 1 and true.',
97
+ ''].join('\n');
98
+ const formatted = assertRoundTrip(src);
99
+ assert.match(formatted, /inner set to \(Inner with x set to 1, y set to 2\), wrapped set to \(some of Inner with x set to k plus 1, y set to 4\), n set to k plus 1, ok set to k at least 1 and true\./);
100
+ });
101
+ test('运算符按中缀输出,括号保持结合与优先级', () => {
102
+ const body = [
103
+ 'Return (a plus b) times c.',
104
+ 'Return a minus (b minus c).',
105
+ 'Return a minus b minus c.',
106
+ 'Return a divided by (b times c).',
107
+ 'Return a integer divided by b modulo c.',
108
+ 'Return (a plus b) at least c.',
109
+ 'Return not (p and q).',
110
+ 'Return not p and q.',
111
+ 'Return p or q and r.',
112
+ 'Return (p or q) and r.',
113
+ 'Return a less than b or a greater than c.',
114
+ 'Return a equals to b and a not equal to c.',
115
+ 'Return a at most (if p then b else c).',
116
+ ];
117
+ const funcs = body.map((line, i) => `Rule f${i} given a as Int, b as Int, c as Int, p as Bool, q as Bool, r as Bool, produce Int:\n ${line}`);
118
+ const formatted = assertRoundTrip(['Module m.', '', ...funcs, ''].join('\n\n'));
119
+ assert.match(formatted, /Return \(a plus b\) times c\./);
120
+ assert.match(formatted, /Return a minus \(b minus c\)\./);
121
+ assert.match(formatted, /Return a minus b minus c\./);
122
+ assert.match(formatted, /Return not \(p and q\)\./);
123
+ });
124
+ });
125
+ //# sourceMappingURL=formatter-roundtrip.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"formatter-roundtrip.test.js","sourceRoot":"","sources":["../../../test/unit/formatter-roundtrip.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=controls-registry-parity.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controls-registry-parity.test.d.ts","sourceRoot":"","sources":["../../../../test/unit/governance/controls-registry-parity.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,28 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { readFileSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { CONTROLS_REGISTRY } from '../../../src/governance/controls-registry.data.js';
6
+ import { locateSiblingSource } from '../../helpers/sibling-source.js';
7
+ // 内置副本与真相源深度相等(ADR 0045 §2.2)。候选依次为:本地兄弟 locales、CI 子目录 locales、
8
+ // CI 已 checkout 的 core classpath 副本(core 侧有自己的 locales 一致性门禁,故传递相等)。
9
+ // CI 中全部缺失即失败;本地未并列 checkout 时跳过。
10
+ test('controls 副本与真相源一致', (t) => {
11
+ const cwd = process.cwd();
12
+ const source = locateSiblingSource([
13
+ join(cwd, '..', 'aster-lang-locales', 'controls', 'registry.json'),
14
+ join(cwd, 'aster-lang-locales', 'controls', 'registry.json'),
15
+ join(cwd, 'aster-lang-core', 'src', 'main', 'resources', 'governance', 'controls-registry.json'),
16
+ ], 'aster-lang-locales 或 aster-lang-core 以校验控制项注册表副本一致性');
17
+ if (source === undefined)
18
+ return t.skip('本地未并列 checkout aster-lang-locales');
19
+ assert.deepEqual(CONTROLS_REGISTRY, JSON.parse(readFileSync(source, 'utf8')));
20
+ });
21
+ test('CI 中真相源缺失即失败而非跳过', () => {
22
+ const missing = [join(process.cwd(), 'no-such-dir', 'registry.json')];
23
+ assert.equal(locateSiblingSource(missing, 'x', {}), undefined);
24
+ assert.equal(locateSiblingSource(missing, 'x', { CI: '' }), undefined);
25
+ assert.throws(() => locateSiblingSource(missing, 'x', { CI: 'true' }), /CI 中必须 checkout x/);
26
+ assert.throws(() => locateSiblingSource(missing, 'x', { GITHUB_ACTIONS: 'true' }), /CI 中必须 checkout x/);
27
+ });
28
+ //# sourceMappingURL=controls-registry-parity.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controls-registry-parity.test.js","sourceRoot":"","sources":["../../../../test/unit/governance/controls-registry-parity.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mDAAmD,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAEtE,iEAAiE;AACjE,qEAAqE;AACrE,kCAAkC;AAClC,IAAI,CAAC,mBAAmB,EAAE,CAAC,CAAC,EAAE,EAAE;IAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,mBAAmB,CAChC;QACE,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,oBAAoB,EAAE,UAAU,EAAE,eAAe,CAAC;QAClE,IAAI,CAAC,GAAG,EAAE,oBAAoB,EAAE,UAAU,EAAE,eAAe,CAAC;QAC5D,IAAI,CAAC,GAAG,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,wBAAwB,CAAC;KACjG,EACD,qDAAqD,CACtD,CAAC;IACF,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,CAAC,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAC;IAC7E,MAAM,CAAC,SAAS,CAAC,iBAAiB,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAC5B,MAAM,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,eAAe,CAAC,CAAC,CAAC;IACtE,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;IAC/D,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;IACvE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,mBAAmB,CAAC,CAAC;IAC5F,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,OAAO,EAAE,GAAG,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,CAAC,EAAE,mBAAmB,CAAC,CAAC;AAC1G,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=controls-registry-profiles.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controls-registry-profiles.test.d.ts","sourceRoot":"","sources":["../../../../test/unit/governance/controls-registry-profiles.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,106 @@
1
+ import { test } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import { canonicalize } from '../../../src/frontend/canonicalizer.js';
4
+ import { lex } from '../../../src/frontend/lexer.js';
5
+ import { parse } from '../../../src/parser.js';
6
+ import { lowerModule } from '../../../src/lower_to_core.js';
7
+ import { typecheckModule } from '../../../src/typecheck.js';
8
+ import { controlRegistryFrom } from '../../../src/governance/controls.js';
9
+ // 注册表档案读取:与 Java ControlRegistryTest 的档案用例逐条对应(规则同 locales 校验口径)。
10
+ // 注入的注册表可能来自运行时 JSON,故以 unknown 构造畸形输入。
11
+ function registryWithProfiles(profiles) {
12
+ return controlRegistryFrom({
13
+ version: '9',
14
+ frameworks: [{ id: 'EU_AI_ACT', title: { en: 'a', zh: 'a', de: 'a' } }],
15
+ controls: [{ key: 'EU_AI_ACT:ART14', framework: 'EU_AI_ACT', article: '14', title: { en: 'a', zh: 'a', de: 'a' } }],
16
+ clauses: [],
17
+ profiles,
18
+ });
19
+ }
20
+ function profile(id, ruleId, registered, frameworks) {
21
+ const requires = { ruleId, registeredControls: registered, frameworks };
22
+ return id === undefined ? { requires } : { id, requires };
23
+ }
24
+ function profileIds(r, candidates) {
25
+ return candidates.filter((id) => r.profile?.(id) !== undefined);
26
+ }
27
+ test('合法档案照常登记', () => {
28
+ const hr = registryWithProfiles([profile('hr', true, false, ['EU_AI_ACT'])]).profile?.('hr');
29
+ assert.deepEqual(hr, { id: 'hr', ruleId: true, registeredControls: false, frameworks: ['EU_AI_ACT'] });
30
+ });
31
+ test('畸形档案不登记且不影响其它档案', () => {
32
+ const good = profile('ok', true, true, []);
33
+ const bad = [
34
+ profile(undefined, true, true, []),
35
+ profile(42, true, true, []),
36
+ profile('Bad_Id', true, true, []),
37
+ profile('x' + 'a'.repeat(64), true, true, []),
38
+ profile('bad', 'yes', true, []),
39
+ profile('bad', true, 1, []),
40
+ profile('bad', true, true, 'EU_AI_ACT'),
41
+ profile('bad', true, true, ['NOPE']),
42
+ profile('bad', true, true, [7]),
43
+ { id: 'bad' },
44
+ ];
45
+ const candidates = ['ok', 'bad', 'Bad_Id', 'x' + 'a'.repeat(64), '42'];
46
+ for (const b of bad) {
47
+ assert.deepEqual(profileIds(registryWithProfiles([good, b]), candidates), ['ok'], JSON.stringify(b));
48
+ }
49
+ });
50
+ test('重复档案 id 全部不登记', () => {
51
+ const r = registryWithProfiles([profile('dup', true, true, []), profile('dup', false, false, []), profile('ok', true, true, [])]);
52
+ assert.equal(r.profile?.('dup'), undefined);
53
+ assert.notEqual(r.profile?.('ok'), undefined);
54
+ });
55
+ test('profiles 不是数组抛出', () => {
56
+ assert.throws(() => registryWithProfiles({}), /profiles/);
57
+ });
58
+ test('profiles 为 null 视为无档案', () => {
59
+ assert.equal(registryWithProfiles(null).profile?.('governed'), undefined);
60
+ });
61
+ test('声明畸形档案的模块得到 E705', () => {
62
+ const r = registryWithProfiles([profile('acme', true, true, ['NOPE'])]);
63
+ const src = 'Module m.\nProfile "acme".\n\nRule r produce Int:\n Return 1.\n';
64
+ const diags = typecheckModule(lowerModule(parse(lex(canonicalize(src))).ast), { controls: r });
65
+ assert.equal(diags.filter((d) => d.code === "E705" /* ErrorCode.GOV_PROFILE_UNKNOWN */).length, 1, JSON.stringify(diags));
66
+ });
67
+ // 根 frameworks 形态不可信:非数组、null/非对象条目、空白 id 都不抛出,只是不计入已登记框架
68
+ function registryWithFrameworks(frameworks) {
69
+ return controlRegistryFrom({
70
+ version: '9',
71
+ frameworks,
72
+ controls: [],
73
+ clauses: [],
74
+ profiles: [profile('ok', true, true, []), profile('blank', true, true, ['']), profile('eu', true, true, ['EU_AI_ACT'])],
75
+ });
76
+ }
77
+ test('根 frameworks 畸形时不抛出,畸形条目与空白 id 不计入', () => {
78
+ const variants = [
79
+ 'EU_AI_ACT',
80
+ null,
81
+ [null, 7, 'EU_AI_ACT', { id: '' }, { id: ' ' }, { id: 3 }],
82
+ ];
83
+ for (const fws of variants) {
84
+ const r = registryWithFrameworks(fws);
85
+ assert.deepEqual(profileIds(r, ['ok', 'blank', 'eu']), ['ok'], JSON.stringify(fws));
86
+ }
87
+ const good = registryWithFrameworks([null, { id: ' ' }, { id: 'EU_AI_ACT' }]);
88
+ assert.deepEqual(profileIds(good, ['ok', 'blank', 'eu']), ['ok', 'eu']);
89
+ });
90
+ // 空白的确切定义:只由 ASCII 空白(空格 \t \n \v \f \r,即 Java 正则默认的 \s)组成;
91
+ // 其它 Unicode 空白(如 NBSP)不算空白,id 照常登记,以便 Java 用 id.matches("\\s*") 得到同一结果
92
+ test('空白 id 只按 ASCII 空白判定', () => {
93
+ for (const blank of ['', ' ', '\t\n\v\f\r ']) {
94
+ const r = controlRegistryFrom({
95
+ version: '9', frameworks: [{ id: blank }], controls: [], clauses: [],
96
+ profiles: [profile('p', true, true, [blank])],
97
+ });
98
+ assert.equal(r.profile?.('p'), undefined, JSON.stringify(blank));
99
+ }
100
+ const nbsp = controlRegistryFrom({
101
+ version: '9', frameworks: [{ id: ' ' }], controls: [], clauses: [],
102
+ profiles: [profile('p', true, true, [' '])],
103
+ });
104
+ assert.deepEqual(nbsp.profile?.('p')?.frameworks, [' ']);
105
+ });
106
+ //# sourceMappingURL=controls-registry-profiles.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controls-registry-profiles.test.js","sourceRoot":"","sources":["../../../../test/unit/governance/controls-registry-profiles.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=governance-check.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"governance-check.test.d.ts","sourceRoot":"","sources":["../../../../test/unit/governance/governance-check.test.ts"],"names":[],"mappings":""}