@greenpandastudios/aug-cli 0.19.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (628) hide show
  1. package/README.md +9 -6
  2. package/THIRD_PARTY_NOTICES.md +4 -0
  3. package/bin/aug.mjs +12 -2
  4. package/docs/about.md +27 -0
  5. package/docs/api/crypto.md +103 -69
  6. package/docs/api/io.md +35 -33
  7. package/docs/api/json.md +3 -3
  8. package/docs/api/memory.md +23 -19
  9. package/docs/api/time.md +10 -9
  10. package/docs/api/web.md +33 -38
  11. package/docs/assets/benchmarks/execution.svg +774 -637
  12. package/docs/assets/benchmarks/http.svg +278 -249
  13. package/docs/assets/benchmarks/improvements.svg +66 -66
  14. package/docs/assets/benchmarks/kernels-mobile.svg +1 -0
  15. package/docs/assets/benchmarks/kernels.svg +1 -0
  16. package/docs/assets/benchmarks/memory.svg +153 -153
  17. package/docs/benchmark-results.json +227089 -90363
  18. package/docs/compatibility.md +8 -8
  19. package/docs/contributing-benchmarks.md +68 -0
  20. package/docs/dev-containers.md +88 -0
  21. package/docs/dgx-consumers.json +122 -0
  22. package/docs/dgx-gyms.json +784 -0
  23. package/docs/dgx-kernels.json +1170 -0
  24. package/docs/dgx-performance.json +227849 -0
  25. package/docs/dgx-spark.md +64 -0
  26. package/docs/diagnostics.md +15 -5
  27. package/docs/docker.md +173 -12
  28. package/docs/editor.md +35 -0
  29. package/docs/example-projects.json +238 -24
  30. package/docs/examples/approved-design/counters.md +34 -126
  31. package/docs/examples/approved-design/dependencies/august/0.21.0/io/contracts.md +178 -0
  32. package/docs/examples/approved-design/domain/app.md +13 -77
  33. package/docs/examples/approved-design/domain/export.md +5 -19
  34. package/docs/examples/approved-design/domain/models.md +4 -23
  35. package/docs/examples/approved-design/domain/numbers.md +24 -114
  36. package/docs/examples/approved-design/index.md +16 -7
  37. package/docs/examples/approved-design/main.md +19 -96
  38. package/docs/examples/benchmark/index.md +6 -5
  39. package/docs/examples/benchmark/main.md +7 -35
  40. package/docs/examples/calls-benchmark/index.md +36 -0
  41. package/docs/examples/calls-benchmark/main.md +78 -0
  42. package/docs/examples/calls-benchmark/operations.md +60 -0
  43. package/docs/examples/cli-args/index.md +6 -5
  44. package/docs/examples/cli-args/main.md +6 -31
  45. package/docs/examples/collections/index.md +6 -5
  46. package/docs/examples/collections/main.md +7 -35
  47. package/docs/examples/collections-benchmark/index.md +6 -5
  48. package/docs/examples/collections-benchmark/main.md +7 -35
  49. package/docs/examples/cpu-benchmark/index.md +6 -5
  50. package/docs/examples/cpu-benchmark/main.md +5 -24
  51. package/docs/examples/developer-workflow/calculator.md +39 -186
  52. package/docs/examples/developer-workflow/dependencies/august/0.21.0/io/contracts.md +178 -0
  53. package/docs/examples/developer-workflow/index.md +16 -7
  54. package/docs/examples/developer-workflow/logging/console.md +10 -56
  55. package/docs/examples/developer-workflow/logging/export.md +4 -14
  56. package/docs/examples/developer-workflow/logging/logger.md +7 -43
  57. package/docs/examples/developer-workflow/main.md +17 -69
  58. package/docs/examples/drop/index.md +6 -5
  59. package/docs/examples/drop/main.md +7 -27
  60. package/docs/examples/drop/resource.md +7 -30
  61. package/docs/examples/errors/errors.md +7 -27
  62. package/docs/examples/errors/index.md +6 -5
  63. package/docs/examples/errors/main.md +7 -28
  64. package/docs/examples/errors-benchmark/index.md +36 -0
  65. package/docs/examples/errors-benchmark/main.md +92 -0
  66. package/docs/examples/errors-benchmark/operations.md +65 -0
  67. package/docs/examples/ffi/index.md +6 -5
  68. package/docs/examples/ffi/main.md +6 -20
  69. package/docs/examples/ffi/native.md +8 -34
  70. package/docs/examples/float-benchmark/index.md +35 -0
  71. package/docs/examples/float-benchmark/main.md +75 -0
  72. package/docs/examples/generic-di/dependencies/august/0.21.0/io/contracts.md +178 -0
  73. package/docs/examples/generic-di/index.md +6 -5
  74. package/docs/examples/generic-di/main.md +9 -39
  75. package/docs/examples/generic-di/types.md +23 -92
  76. package/docs/examples/generics/index.md +6 -5
  77. package/docs/examples/generics/main.md +10 -47
  78. package/docs/examples/generics/types.md +25 -100
  79. package/docs/examples/hello/app/export.md +4 -12
  80. package/docs/examples/hello/app/greeter.md +13 -91
  81. package/docs/examples/hello/dependencies/august/0.21.0/io/contracts.md +178 -0
  82. package/docs/examples/hello/index.md +17 -6
  83. package/docs/examples/hello/logging/console.md +10 -54
  84. package/docs/examples/hello/logging/export.md +4 -14
  85. package/docs/examples/hello/logging/logger.md +7 -45
  86. package/docs/examples/hello/main.md +9 -39
  87. package/docs/examples/http-benchmark/index.md +6 -5
  88. package/docs/examples/http-benchmark/main.md +6 -20
  89. package/docs/examples/http-benchmark/routes.md +9 -31
  90. package/docs/examples/index.md +63 -29
  91. package/docs/examples/interceptors/app.md +20 -139
  92. package/docs/examples/interceptors/dependencies/august/0.21.0/io/contracts.md +178 -0
  93. package/docs/examples/interceptors/index.md +6 -5
  94. package/docs/examples/interceptors/interceptors.md +24 -148
  95. package/docs/examples/interceptors/logging.md +13 -76
  96. package/docs/examples/interceptors/main.md +10 -65
  97. package/docs/examples/json-benchmark/data.md +4 -20
  98. package/docs/examples/json-benchmark/dependencies/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +67 -0
  99. package/docs/examples/json-benchmark/index.md +7 -5
  100. package/docs/examples/json-benchmark/main-yaml.md +20 -0
  101. package/docs/examples/json-benchmark/main.md +10 -49
  102. package/docs/examples/list-benchmark/index.md +35 -0
  103. package/docs/examples/list-benchmark/main.md +78 -0
  104. package/docs/examples/map-churn-benchmark/index.md +35 -0
  105. package/docs/examples/map-churn-benchmark/main.md +106 -0
  106. package/docs/examples/native-blake3/dependencies/packages/@greenpandastudios/aug-blake3/0.1.3/api.md +104 -0
  107. package/docs/examples/native-blake3/dependencies/packages/@greenpandastudios/aug-blake3/0.1.3/contracts.md +54 -0
  108. package/docs/examples/native-blake3/dependencies/packages/@greenpandastudios/aug-blake3/0.1.3/native.abi-json.md +48 -0
  109. package/docs/examples/native-blake3/hashing.md +93 -0
  110. package/docs/examples/native-blake3/index.md +38 -0
  111. package/docs/examples/native-blake3/main.md +73 -0
  112. package/docs/examples/native-pytorch/dependencies/packages/@greenpandastudios/aug-pytorch/0.1.4/api.md +406 -0
  113. package/docs/examples/native-pytorch/dependencies/packages/@greenpandastudios/aug-pytorch/0.1.4/bindings.md +51 -0
  114. package/docs/examples/native-pytorch/dependencies/packages/@greenpandastudios/aug-pytorch/0.1.4/contracts.md +63 -0
  115. package/docs/examples/native-pytorch/dependencies/packages/@greenpandastudios/aug-pytorch/0.1.4/native.abi-json.md +161 -0
  116. package/docs/examples/native-pytorch/index.md +38 -0
  117. package/docs/examples/native-pytorch/main.md +73 -0
  118. package/docs/examples/native-pytorch/tensors.md +123 -0
  119. package/docs/examples/native-sqlite/database.md +116 -0
  120. package/docs/examples/native-sqlite/dependencies/packages/@greenpandastudios/aug-sqlite/0.1.3/api.md +284 -0
  121. package/docs/examples/native-sqlite/dependencies/packages/@greenpandastudios/aug-sqlite/0.1.3/bindings.md +51 -0
  122. package/docs/examples/native-sqlite/dependencies/packages/@greenpandastudios/aug-sqlite/0.1.3/contracts.md +75 -0
  123. package/docs/examples/native-sqlite/dependencies/packages/@greenpandastudios/aug-sqlite/0.1.3/native.abi-json.md +119 -0
  124. package/docs/examples/native-sqlite/index.md +38 -0
  125. package/docs/examples/native-sqlite/main.md +73 -0
  126. package/docs/examples/native-zlib/compression.md +99 -0
  127. package/docs/examples/native-zlib/dependencies/packages/@greenpandastudios/aug-zlib/0.1.3/api.md +153 -0
  128. package/docs/examples/native-zlib/dependencies/packages/@greenpandastudios/aug-zlib/0.1.3/contracts.md +54 -0
  129. package/docs/examples/native-zlib/dependencies/packages/@greenpandastudios/aug-zlib/0.1.3/native.abi-json.md +76 -0
  130. package/docs/examples/native-zlib/index.md +38 -0
  131. package/docs/examples/native-zlib/main.md +78 -0
  132. package/docs/examples/new-syntax/console.md +10 -52
  133. package/docs/examples/new-syntax/dependencies/august/0.21.0/io/contracts.md +178 -0
  134. package/docs/examples/new-syntax/greeter.md +13 -71
  135. package/docs/examples/new-syntax/index.md +6 -5
  136. package/docs/examples/new-syntax/logger.md +7 -43
  137. package/docs/examples/new-syntax/main.md +10 -53
  138. package/docs/examples/new-syntax/math.md +6 -24
  139. package/docs/examples/oidc-login/client/contracts.md +10 -61
  140. package/docs/examples/oidc-login/client/endpoints.md +32 -154
  141. package/docs/examples/oidc-login/client/export.md +5 -23
  142. package/docs/examples/oidc-login/client/login.md +234 -344
  143. package/docs/examples/oidc-login/client/logout.md +38 -143
  144. package/docs/examples/oidc-login/client/protocol.md +183 -304
  145. package/docs/examples/oidc-login/client/session.md +41 -149
  146. package/docs/examples/oidc-login/client/views.md +13 -58
  147. package/docs/examples/oidc-login/common/export.md +6 -26
  148. package/docs/examples/oidc-login/common/headers.md +42 -72
  149. package/docs/examples/oidc-login/common/keys.md +40 -164
  150. package/docs/examples/oidc-login/common/settings.md +24 -40
  151. package/docs/examples/oidc-login/common/views.md +7 -28
  152. package/docs/examples/oidc-login/dependencies/packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.md +205 -0
  153. package/docs/examples/oidc-login/dependencies/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +67 -0
  154. package/docs/examples/oidc-login/dependencies/packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +267 -0
  155. package/docs/examples/oidc-login/dependencies/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.md +415 -0
  156. package/docs/examples/oidc-login/dependencies/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.md +271 -0
  157. package/docs/examples/oidc-login/dependencies/packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.md +89 -0
  158. package/docs/examples/oidc-login/index.md +8 -7
  159. package/docs/examples/oidc-login/main-yaml.md +7 -0
  160. package/docs/examples/oidc-login/main.md +26 -153
  161. package/docs/examples/oidc-login/provider/authorization.md +232 -275
  162. package/docs/examples/oidc-login/provider/contracts.md +24 -146
  163. package/docs/examples/oidc-login/provider/credentials.md +24 -57
  164. package/docs/examples/oidc-login/provider/discovery.md +48 -122
  165. package/docs/examples/oidc-login/provider/export.md +11 -37
  166. package/docs/examples/oidc-login/provider/token.md +159 -237
  167. package/docs/examples/oidc-login/provider/userinfo.md +47 -102
  168. package/docs/examples/oidc-login/provider/views.md +13 -53
  169. package/docs/examples/ownership/counter.md +17 -63
  170. package/docs/examples/ownership/index.md +6 -5
  171. package/docs/examples/ownership/main.md +7 -30
  172. package/docs/examples/ownership-transfer/dependencies/august/0.21.0/io/contracts.md +178 -0
  173. package/docs/examples/ownership-transfer/index.md +6 -5
  174. package/docs/examples/ownership-transfer/main.md +10 -52
  175. package/docs/examples/ownership-transfer/resource.md +15 -67
  176. package/docs/examples/packages-app/dependencies/packages/@example/aug-math/0.1.0/arithmetic.md +12 -50
  177. package/docs/examples/packages-app/index.md +7 -6
  178. package/docs/examples/packages-app/main.md +7 -25
  179. package/docs/examples/packages-math/aug-package-json.md +1 -1
  180. package/docs/examples/packages-math/index.md +7 -6
  181. package/docs/examples/packages-math/src/arithmetic.md +12 -50
  182. package/docs/examples/packages-math/src/export.md +4 -12
  183. package/docs/examples/records-benchmark/data.md +55 -0
  184. package/docs/examples/records-benchmark/index.md +36 -0
  185. package/docs/examples/records-benchmark/main.md +85 -0
  186. package/docs/examples/startup-benchmark/index.md +6 -5
  187. package/docs/examples/startup-benchmark/main.md +5 -17
  188. package/docs/examples/strings-benchmark/index.md +35 -0
  189. package/docs/examples/strings-benchmark/main.md +76 -0
  190. package/docs/examples/tasks-benchmark/index.md +36 -0
  191. package/docs/examples/tasks-benchmark/main.md +89 -0
  192. package/docs/examples/tasks-benchmark/operations.md +58 -0
  193. package/docs/examples/visibility/counter.md +19 -67
  194. package/docs/examples/visibility/index.md +6 -5
  195. package/docs/examples/visibility/main.md +7 -31
  196. package/docs/examples/weather-api/forecasts.md +168 -0
  197. package/docs/examples/weather-api/index.md +42 -0
  198. package/docs/examples/weather-api/main-yaml.md +21 -0
  199. package/docs/examples/weather-api/main.md +65 -0
  200. package/docs/examples.json +10 -0
  201. package/docs/getting-started.md +105 -2
  202. package/docs/grammar.md +7 -5
  203. package/docs/guides/change-a-module.md +64 -0
  204. package/docs/guides/index.md +27 -0
  205. package/docs/gym-results.json +784 -0
  206. package/docs/implementation-map.md +6 -0
  207. package/docs/index.md +51 -29
  208. package/docs/kernel-results.json +1170 -0
  209. package/docs/language-conformance.md +7 -1
  210. package/docs/language-constructs.md +30 -22
  211. package/docs/language-design-audit.md +1 -1
  212. package/docs/learn/data-and-errors.md +77 -0
  213. package/docs/learn/index.md +30 -0
  214. package/docs/learn/modules-and-dependencies.md +73 -0
  215. package/docs/learn/state-and-tests.md +71 -0
  216. package/docs/learn/values-and-functions.md +62 -0
  217. package/docs/lesson-failures.json +8 -0
  218. package/docs/maintaining-docs.md +16 -4
  219. package/docs/native-implementation.md +276 -0
  220. package/docs/native-interop-llvm-plan.md +342 -0
  221. package/docs/native-package-examples.md +684 -0
  222. package/docs/native-packages.md +179 -0
  223. package/docs/packages.md +72 -126
  224. package/docs/performance.md +61 -68
  225. package/docs/production-readiness.md +16 -5
  226. package/docs/public/downloads/approved-design.zip +0 -0
  227. package/docs/public/downloads/benchmark.zip +0 -0
  228. package/docs/public/downloads/calls-benchmark.zip +0 -0
  229. package/docs/public/downloads/cli-args.zip +0 -0
  230. package/docs/public/downloads/collections-benchmark.zip +0 -0
  231. package/docs/public/downloads/collections.zip +0 -0
  232. package/docs/public/downloads/cpu-benchmark.zip +0 -0
  233. package/docs/public/downloads/developer-workflow.zip +0 -0
  234. package/docs/public/downloads/drop.zip +0 -0
  235. package/docs/public/downloads/errors-benchmark.zip +0 -0
  236. package/docs/public/downloads/errors.zip +0 -0
  237. package/docs/public/downloads/ffi.zip +0 -0
  238. package/docs/public/downloads/float-benchmark.zip +0 -0
  239. package/docs/public/downloads/generic-di.zip +0 -0
  240. package/docs/public/downloads/generics.zip +0 -0
  241. package/docs/public/downloads/hello.zip +0 -0
  242. package/docs/public/downloads/http-benchmark.zip +0 -0
  243. package/docs/public/downloads/interceptors.zip +0 -0
  244. package/docs/public/downloads/json-benchmark.zip +0 -0
  245. package/docs/public/downloads/list-benchmark.zip +0 -0
  246. package/docs/public/downloads/map-churn-benchmark.zip +0 -0
  247. package/docs/public/downloads/native-blake3.zip +0 -0
  248. package/docs/public/downloads/native-pytorch.zip +0 -0
  249. package/docs/public/downloads/native-sqlite.zip +0 -0
  250. package/docs/public/downloads/native-zlib.zip +0 -0
  251. package/docs/public/downloads/new-syntax.zip +0 -0
  252. package/docs/public/downloads/oidc-login.zip +0 -0
  253. package/docs/public/downloads/ownership-transfer.zip +0 -0
  254. package/docs/public/downloads/ownership.zip +0 -0
  255. package/docs/public/downloads/packages-app.zip +0 -0
  256. package/docs/public/downloads/packages-math.zip +0 -0
  257. package/docs/public/downloads/records-benchmark.zip +0 -0
  258. package/docs/public/downloads/startup-benchmark.zip +0 -0
  259. package/docs/public/downloads/strings-benchmark.zip +0 -0
  260. package/docs/public/downloads/tasks-benchmark.zip +0 -0
  261. package/docs/public/downloads/visibility.zip +0 -0
  262. package/docs/public/downloads/weather-api.zip +0 -0
  263. package/docs/qualification-results.md +66 -0
  264. package/docs/reference.md +47 -17
  265. package/docs/releasing.md +105 -16
  266. package/docs/research/code-to-natural-language.md +108 -0
  267. package/docs/research/ecosystem-workflow.md +41 -0
  268. package/docs/research/libtorch-native-qualification.md +115 -0
  269. package/docs/research/native-interop-llvm.md +197 -0
  270. package/docs/research/qualification-methods.md +15 -0
  271. package/docs/research/wiki-editorial-design.md +71 -0
  272. package/docs/roadmap.md +2 -1
  273. package/docs/safety-gyms.md +41 -0
  274. package/docs/specifications.md +27 -11
  275. package/docs/testing.md +19 -5
  276. package/docs/tooling.md +36 -22
  277. package/docs/weather-api.md +65 -0
  278. package/docs/web-library-gaps.md +1 -1
  279. package/docs/web.md +54 -18
  280. package/docs/writing-docs.md +49 -0
  281. package/examples/{hello/.aug-spec/august/0.19.0 → approved-design/.aug-spec/august/0.21.0}/io/contracts.aug +4 -3
  282. package/examples/approved-design/.aug-spec/august/0.21.0/io/contracts.aug.md +82 -0
  283. package/examples/approved-design/.aug-spec/manifest.json +3 -3
  284. package/examples/approved-design/counters.aug +5 -4
  285. package/examples/approved-design/counters.aug.md +25 -132
  286. package/examples/approved-design/domain/app.aug +2 -1
  287. package/examples/approved-design/domain/app.aug.md +10 -80
  288. package/examples/approved-design/domain/export.aug +1 -0
  289. package/examples/approved-design/domain/export.aug.md +4 -20
  290. package/examples/approved-design/domain/models.aug +1 -0
  291. package/examples/approved-design/domain/models.aug.md +3 -25
  292. package/examples/approved-design/domain/numbers.aug +3 -2
  293. package/examples/approved-design/domain/numbers.aug.md +19 -116
  294. package/examples/approved-design/main.aug +1 -0
  295. package/examples/approved-design/main.aug.md +12 -95
  296. package/examples/benchmark/.aug-spec/manifest.json +1 -1
  297. package/examples/benchmark/main.aug +1 -0
  298. package/examples/benchmark/main.aug.md +6 -36
  299. package/examples/cli-args/.aug-spec/manifest.json +1 -1
  300. package/examples/cli-args/main.aug +1 -0
  301. package/examples/cli-args/main.aug.md +5 -32
  302. package/examples/collections/.aug-spec/manifest.json +1 -1
  303. package/examples/collections/main.aug +1 -0
  304. package/examples/collections/main.aug.md +6 -36
  305. package/examples/{generic-di/.aug-spec/august/0.19.0 → developer-workflow/.aug-spec/august/0.21.0}/io/contracts.aug +4 -3
  306. package/examples/developer-workflow/.aug-spec/august/0.21.0/io/contracts.aug.md +82 -0
  307. package/examples/developer-workflow/.aug-spec/manifest.json +3 -3
  308. package/examples/developer-workflow/calculator.aug +3 -2
  309. package/examples/developer-workflow/calculator.aug.md +28 -189
  310. package/examples/developer-workflow/logging/console.aug +2 -1
  311. package/examples/developer-workflow/logging/console.aug.md +7 -57
  312. package/examples/developer-workflow/logging/export.aug +1 -0
  313. package/examples/developer-workflow/logging/export.aug.md +3 -15
  314. package/examples/developer-workflow/logging/logger.aug +1 -0
  315. package/examples/developer-workflow/logging/logger.aug.md +6 -46
  316. package/examples/developer-workflow/main.aug +1 -0
  317. package/examples/developer-workflow/main.aug.md +10 -68
  318. package/examples/drop/.aug-spec/manifest.json +1 -1
  319. package/examples/drop/main.aug +1 -0
  320. package/examples/drop/main.aug.md +6 -28
  321. package/examples/drop/resource.aug +1 -0
  322. package/examples/drop/resource.aug.md +6 -34
  323. package/examples/errors/.aug-spec/manifest.json +1 -1
  324. package/examples/errors/errors.aug +2 -1
  325. package/examples/errors/errors.aug.md +4 -27
  326. package/examples/errors/main.aug +1 -0
  327. package/examples/errors/main.aug.md +6 -29
  328. package/examples/ffi/.aug-spec/manifest.json +1 -1
  329. package/examples/ffi/main.aug +1 -0
  330. package/examples/ffi/main.aug.md +5 -21
  331. package/examples/ffi/native.aug +2 -1
  332. package/examples/ffi/native.aug.md +5 -35
  333. package/examples/{approved-design/.aug-spec/august/0.19.0 → generic-di/.aug-spec/august/0.21.0}/io/contracts.aug +4 -3
  334. package/examples/generic-di/.aug-spec/august/0.21.0/io/contracts.aug.md +82 -0
  335. package/examples/generic-di/.aug-spec/manifest.json +3 -3
  336. package/examples/generic-di/main.aug +1 -0
  337. package/examples/generic-di/main.aug.md +8 -40
  338. package/examples/generic-di/types.aug +3 -2
  339. package/examples/generic-di/types.aug.md +18 -97
  340. package/examples/generics/.aug-spec/manifest.json +1 -1
  341. package/examples/generics/main.aug +1 -0
  342. package/examples/generics/main.aug.md +9 -48
  343. package/examples/generics/types.aug +4 -3
  344. package/examples/generics/types.aug.md +18 -104
  345. package/examples/{developer-workflow/.aug-spec/august/0.19.0 → hello/.aug-spec/august/0.21.0}/io/contracts.aug +4 -3
  346. package/examples/hello/.aug-spec/august/0.21.0/io/contracts.aug.md +82 -0
  347. package/examples/hello/.aug-spec/manifest.json +3 -3
  348. package/examples/hello/app/export.aug +1 -0
  349. package/examples/hello/app/export.aug.md +3 -13
  350. package/examples/hello/app/greeter.aug +2 -1
  351. package/examples/hello/app/greeter.aug.md +10 -94
  352. package/examples/hello/logging/console.aug +2 -1
  353. package/examples/hello/logging/console.aug.md +7 -55
  354. package/examples/hello/logging/export.aug +1 -0
  355. package/examples/hello/logging/export.aug.md +3 -15
  356. package/examples/hello/logging/logger.aug +1 -0
  357. package/examples/hello/logging/logger.aug.md +6 -48
  358. package/examples/hello/main.aug +1 -0
  359. package/examples/hello/main.aug.md +8 -40
  360. package/examples/interceptors/.aug-spec/august/0.21.0/io/contracts.aug +37 -0
  361. package/examples/interceptors/.aug-spec/august/0.21.0/io/contracts.aug.md +82 -0
  362. package/examples/interceptors/.aug-spec/manifest.json +3 -3
  363. package/examples/interceptors/app.aug +3 -2
  364. package/examples/interceptors/app.aug.md +15 -141
  365. package/examples/interceptors/interceptors.aug +3 -2
  366. package/examples/interceptors/interceptors.aug.md +19 -152
  367. package/examples/interceptors/logging.aug +2 -1
  368. package/examples/interceptors/logging.aug.md +10 -79
  369. package/examples/interceptors/main.aug +1 -0
  370. package/examples/interceptors/main.aug.md +9 -66
  371. package/examples/native-blake3/.aug-spec/manifest.json +16 -0
  372. package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.1/native.abi.json +29 -0
  373. package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.3/api.aug +14 -0
  374. package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.3/api.aug.md +34 -0
  375. package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.3/contracts.aug +4 -0
  376. package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.3/contracts.aug.md +8 -0
  377. package/examples/native-blake3/.aug-spec/packages/@greenpandastudios/aug-blake3/0.1.3/native.abi.json +29 -0
  378. package/examples/native-blake3/AGENTS.md +5 -0
  379. package/examples/native-blake3/aug.lock.json +253 -0
  380. package/examples/native-blake3/hashing.aug +11 -0
  381. package/examples/native-blake3/hashing.aug.md +25 -0
  382. package/examples/native-blake3/main.aug +8 -0
  383. package/examples/native-blake3/main.aug.md +13 -0
  384. package/examples/native-pytorch/.aug-spec/manifest.json +18 -0
  385. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.1/native.abi.json +142 -0
  386. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.3/native.abi.json +142 -0
  387. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/api.aug +101 -0
  388. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/api.aug.md +160 -0
  389. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/bindings.aug +3 -0
  390. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/bindings.aug.md +8 -0
  391. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/contracts.aug +6 -0
  392. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/contracts.aug.md +13 -0
  393. package/examples/native-pytorch/.aug-spec/packages/@greenpandastudios/aug-pytorch/0.1.4/native.abi.json +142 -0
  394. package/examples/native-pytorch/AGENTS.md +5 -0
  395. package/examples/native-pytorch/aug.lock.json +309 -0
  396. package/examples/native-pytorch/main.aug +8 -0
  397. package/examples/native-pytorch/main.aug.md +13 -0
  398. package/examples/native-pytorch/tensors.aug +23 -0
  399. package/examples/native-pytorch/tensors.aug.md +35 -0
  400. package/examples/native-sqlite/.aug-spec/manifest.json +18 -0
  401. package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.2/native.abi.json +100 -0
  402. package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/api.aug +48 -0
  403. package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/api.aug.md +91 -0
  404. package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/bindings.aug +3 -0
  405. package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/bindings.aug.md +8 -0
  406. package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/contracts.aug +8 -0
  407. package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/contracts.aug.md +22 -0
  408. package/examples/native-sqlite/.aug-spec/packages/@greenpandastudios/aug-sqlite/0.1.3/native.abi.json +100 -0
  409. package/examples/native-sqlite/AGENTS.md +5 -0
  410. package/examples/native-sqlite/aug.lock.json +236 -0
  411. package/examples/native-sqlite/database.aug +15 -0
  412. package/examples/native-sqlite/database.aug.md +27 -0
  413. package/examples/native-sqlite/main.aug +8 -0
  414. package/examples/native-sqlite/main.aug.md +13 -0
  415. package/examples/native-zlib/.aug-spec/manifest.json +16 -0
  416. package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.1/native.abi.json +57 -0
  417. package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.3/api.aug +29 -0
  418. package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.3/api.aug.md +54 -0
  419. package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.3/contracts.aug +4 -0
  420. package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.3/contracts.aug.md +8 -0
  421. package/examples/native-zlib/.aug-spec/packages/@greenpandastudios/aug-zlib/0.1.3/native.abi.json +57 -0
  422. package/examples/native-zlib/AGENTS.md +5 -0
  423. package/examples/native-zlib/aug.lock.json +236 -0
  424. package/examples/native-zlib/compression.aug +15 -0
  425. package/examples/native-zlib/compression.aug.md +27 -0
  426. package/examples/native-zlib/main.aug +10 -0
  427. package/examples/native-zlib/main.aug.md +13 -0
  428. package/examples/new-syntax/.aug-spec/august/0.21.0/io/contracts.aug +37 -0
  429. package/examples/new-syntax/.aug-spec/august/0.21.0/io/contracts.aug.md +82 -0
  430. package/examples/new-syntax/.aug-spec/manifest.json +3 -3
  431. package/examples/new-syntax/console.aug +2 -1
  432. package/examples/new-syntax/console.aug.md +7 -53
  433. package/examples/new-syntax/greeter.aug +2 -1
  434. package/examples/new-syntax/greeter.aug.md +10 -74
  435. package/examples/new-syntax/logger.aug +1 -0
  436. package/examples/new-syntax/logger.aug.md +6 -46
  437. package/examples/new-syntax/main.aug +1 -0
  438. package/examples/new-syntax/main.aug.md +9 -54
  439. package/examples/new-syntax/math.aug +2 -1
  440. package/examples/new-syntax/math.aug.md +3 -24
  441. package/examples/oidc-login/.aug-spec/manifest.json +13 -13
  442. package/examples/oidc-login/.aug-spec/packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/store.aug.md +71 -0
  443. package/examples/oidc-login/.aug-spec/packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +17 -0
  444. package/examples/oidc-login/.aug-spec/packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +125 -0
  445. package/examples/oidc-login/.aug-spec/{august/0.19.0/crypto → packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40}/contracts.aug +12 -11
  446. package/examples/oidc-login/.aug-spec/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/contracts.aug.md +244 -0
  447. package/examples/oidc-login/.aug-spec/{august/0.19.0/crypto → packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40}/jose.aug +6 -5
  448. package/examples/oidc-login/.aug-spec/packages/@git/url_9ef654c66d34ab8f5527/0.0.0-git.b14a0f9aa41f1ce58bd51133bcdc424033e40d40/jose.aug.md +71 -0
  449. package/examples/oidc-login/.aug-spec/packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301/contracts.aug.md +30 -0
  450. package/examples/oidc-login/aug.lock.json +100 -0
  451. package/examples/oidc-login/client/contracts.aug +1 -0
  452. package/examples/oidc-login/client/contracts.aug.md +9 -66
  453. package/examples/oidc-login/client/endpoints.aug +6 -5
  454. package/examples/oidc-login/client/endpoints.aug.md +13 -145
  455. package/examples/oidc-login/client/export.aug +1 -0
  456. package/examples/oidc-login/client/export.aug.md +4 -24
  457. package/examples/oidc-login/client/login.aug +7 -6
  458. package/examples/oidc-login/client/login.aug.md +25 -303
  459. package/examples/oidc-login/client/logout.aug +5 -4
  460. package/examples/oidc-login/client/logout.aug.md +13 -135
  461. package/examples/oidc-login/client/protocol.aug +7 -6
  462. package/examples/oidc-login/client/protocol.aug.md +36 -283
  463. package/examples/oidc-login/client/session.aug +5 -4
  464. package/examples/oidc-login/client/session.aug.md +12 -139
  465. package/examples/oidc-login/client/views.aug +3 -2
  466. package/examples/oidc-login/client/views.aug.md +8 -57
  467. package/examples/oidc-login/common/export.aug +1 -0
  468. package/examples/oidc-login/common/export.aug.md +5 -27
  469. package/examples/oidc-login/common/headers.aug +4 -3
  470. package/examples/oidc-login/common/headers.aug.md +9 -67
  471. package/examples/oidc-login/common/keys.aug +6 -5
  472. package/examples/oidc-login/common/keys.aug.md +29 -165
  473. package/examples/oidc-login/common/settings.aug +2 -1
  474. package/examples/oidc-login/common/settings.aug.md +5 -39
  475. package/examples/oidc-login/common/views.aug +2 -1
  476. package/examples/oidc-login/common/views.aug.md +4 -28
  477. package/examples/oidc-login/main.aug +6 -16
  478. package/examples/oidc-login/main.aug.md +17 -146
  479. package/examples/oidc-login/main.yaml +7 -0
  480. package/examples/oidc-login/provider/authorization.aug +7 -6
  481. package/examples/oidc-login/provider/authorization.aug.md +23 -238
  482. package/examples/oidc-login/provider/contracts.aug +1 -0
  483. package/examples/oidc-login/provider/contracts.aug.md +23 -158
  484. package/examples/oidc-login/provider/credentials.aug +3 -2
  485. package/examples/oidc-login/provider/credentials.aug.md +9 -53
  486. package/examples/oidc-login/provider/discovery.aug +4 -3
  487. package/examples/oidc-login/provider/discovery.aug.md +11 -118
  488. package/examples/oidc-login/provider/export.aug +1 -0
  489. package/examples/oidc-login/provider/export.aug.md +6 -34
  490. package/examples/oidc-login/provider/token.aug +6 -5
  491. package/examples/oidc-login/provider/token.aug.md +16 -204
  492. package/examples/oidc-login/provider/userinfo.aug +4 -3
  493. package/examples/oidc-login/provider/userinfo.aug.md +10 -92
  494. package/examples/oidc-login/provider/views.aug +3 -2
  495. package/examples/oidc-login/provider/views.aug.md +8 -52
  496. package/examples/ownership/.aug-spec/manifest.json +1 -1
  497. package/examples/ownership/counter.aug +3 -2
  498. package/examples/ownership/counter.aug.md +12 -66
  499. package/examples/ownership/main.aug +1 -0
  500. package/examples/ownership/main.aug.md +6 -31
  501. package/examples/ownership-transfer/.aug-spec/august/0.21.0/io/contracts.aug +37 -0
  502. package/examples/ownership-transfer/.aug-spec/august/0.21.0/io/contracts.aug.md +82 -0
  503. package/examples/ownership-transfer/.aug-spec/manifest.json +3 -3
  504. package/examples/ownership-transfer/main.aug +1 -0
  505. package/examples/ownership-transfer/main.aug.md +9 -53
  506. package/examples/ownership-transfer/resource.aug +2 -1
  507. package/examples/ownership-transfer/resource.aug.md +12 -71
  508. package/examples/packages/app/.aug-spec/manifest.json +1 -1
  509. package/examples/packages/app/.aug-spec/packages/@example/aug-math/0.1.0/arithmetic.aug +2 -1
  510. package/examples/packages/app/.aug-spec/packages/@example/aug-math/0.1.0/arithmetic.aug.md +9 -51
  511. package/examples/packages/app/main.aug +1 -0
  512. package/examples/packages/app/main.aug.md +6 -26
  513. package/examples/packages/math/.aug-spec/manifest.json +1 -1
  514. package/examples/packages/math/aug-package.json +1 -1
  515. package/examples/packages/math/src/arithmetic.aug +2 -1
  516. package/examples/packages/math/src/arithmetic.aug.md +9 -51
  517. package/examples/packages/math/src/export.aug +1 -0
  518. package/examples/packages/math/src/export.aug.md +3 -13
  519. package/examples/visibility/.aug-spec/manifest.json +1 -1
  520. package/examples/visibility/counter.aug +4 -3
  521. package/examples/visibility/counter.aug.md +12 -68
  522. package/examples/visibility/main.aug +1 -0
  523. package/examples/visibility/main.aug.md +6 -32
  524. package/examples/weather-api/.aug-spec/manifest.json +8 -0
  525. package/examples/weather-api/AGENTS.md +17 -0
  526. package/examples/weather-api/README.md +19 -0
  527. package/examples/weather-api/forecasts.aug +47 -0
  528. package/examples/weather-api/forecasts.aug.md +32 -0
  529. package/examples/weather-api/main.aug +4 -0
  530. package/examples/weather-api/main.aug.md +15 -0
  531. package/examples/weather-api/main.yaml +5 -0
  532. package/examples/weather-api/weather.http +5 -0
  533. package/native/compiler-packs.json +43 -0
  534. package/package.json +4 -4
  535. package/runtime/aug_http.c +48 -21
  536. package/runtime/aug_http_ir.c +30 -0
  537. package/runtime/aug_http_ir.h +18 -0
  538. package/runtime/aug_ir.c +209 -0
  539. package/runtime/aug_ir.h +89 -0
  540. package/runtime/aug_json.c +6 -1
  541. package/runtime/aug_runtime.c +82 -16
  542. package/runtime/aug_runtime.h +16 -2
  543. package/runtime/aug_tasks.c +38 -7
  544. package/runtime/aug_values.c +12 -6
  545. package/scripts/bootstrap-native.mjs +184 -106
  546. package/scripts/native-setup.mjs +98 -0
  547. package/scripts/native-toolchain.mjs +28 -0
  548. package/src/ast.js +1 -1
  549. package/src/builtins.js +1 -1
  550. package/src/checker.js +369 -100
  551. package/src/cli.js +198 -26
  552. package/src/codegen.js +32 -7
  553. package/src/compiler-packs.js +66 -0
  554. package/src/config.js +3 -3
  555. package/src/contracts.js +10 -0
  556. package/src/editor.js +86 -22
  557. package/src/fixes.js +90 -2
  558. package/src/formatter.js +23 -10
  559. package/src/git-http.js +137 -0
  560. package/src/git-packages.js +118 -0
  561. package/src/help.js +33 -24
  562. package/src/http-contracts.js +14 -0
  563. package/src/http-policies.js +5 -5
  564. package/src/ir-types.js +5 -0
  565. package/src/ir-verify.js +277 -0
  566. package/src/ir.js +962 -0
  567. package/src/libraries.js +1 -1
  568. package/src/llvm-debug.js +101 -0
  569. package/src/llvm-native.js +152 -0
  570. package/src/llvm-platform.js +20 -0
  571. package/src/llvm.js +781 -0
  572. package/src/lsp.js +14 -5
  573. package/src/native-artifacts.js +207 -0
  574. package/src/native-bindings.js +189 -0
  575. package/src/native-contracts.js +295 -0
  576. package/src/native-declarations.js +68 -0
  577. package/src/native-facts.js +63 -0
  578. package/src/native.js +19 -13
  579. package/src/navigation.js +4 -2
  580. package/src/openapi.js +5 -4
  581. package/src/package-locking.js +88 -0
  582. package/src/package-manager.js +267 -68
  583. package/src/parser.js +32 -6
  584. package/src/policies.js +3 -3
  585. package/src/project-init.js +78 -4
  586. package/src/project.js +11 -9
  587. package/src/runtime-abi.js +23 -0
  588. package/src/runtime-adapters.js +18 -0
  589. package/src/schemas.js +24 -17
  590. package/src/semantic.js +54 -5
  591. package/src/snippets.js +60 -0
  592. package/src/spec-hints.js +56 -0
  593. package/src/spec-tree.js +241 -0
  594. package/src/spec.js +669 -305
  595. package/docs/examples/approved-design/dependencies/august/0.19.0/io/contracts.md +0 -395
  596. package/docs/examples/developer-workflow/dependencies/august/0.19.0/io/contracts.md +0 -395
  597. package/docs/examples/generic-di/dependencies/august/0.19.0/io/contracts.md +0 -395
  598. package/docs/examples/hello/dependencies/august/0.19.0/io/contracts.md +0 -395
  599. package/docs/examples/interceptors/dependencies/august/0.19.0/io/contracts.md +0 -395
  600. package/docs/examples/json-benchmark/dependencies/august/0.19.0/json/contracts.md +0 -103
  601. package/docs/examples/new-syntax/dependencies/august/0.19.0/io/contracts.md +0 -395
  602. package/docs/examples/oidc-login/dependencies/august/0.19.0/crypto/contracts.md +0 -925
  603. package/docs/examples/oidc-login/dependencies/august/0.19.0/crypto/jose.md +0 -434
  604. package/docs/examples/oidc-login/dependencies/august/0.19.0/json/contracts.md +0 -103
  605. package/docs/examples/oidc-login/dependencies/august/0.19.0/memory/store.md +0 -374
  606. package/docs/examples/oidc-login/dependencies/august/0.19.0/time/contracts.md +0 -150
  607. package/docs/examples/oidc-login/dependencies/august/0.19.0/web/contracts.md +0 -532
  608. package/docs/examples/ownership-transfer/dependencies/august/0.19.0/io/contracts.md +0 -395
  609. package/examples/approved-design/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  610. package/examples/developer-workflow/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  611. package/examples/generic-di/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  612. package/examples/hello/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  613. package/examples/interceptors/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
  614. package/examples/interceptors/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  615. package/examples/new-syntax/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
  616. package/examples/new-syntax/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  617. package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/contracts.aug.md +0 -791
  618. package/examples/oidc-login/.aug-spec/august/0.19.0/crypto/jose.aug.md +0 -266
  619. package/examples/oidc-login/.aug-spec/august/0.19.0/json/contracts.aug.md +0 -55
  620. package/examples/oidc-login/.aug-spec/august/0.19.0/memory/store.aug.md +0 -250
  621. package/examples/oidc-login/.aug-spec/august/0.19.0/time/contracts.aug.md +0 -96
  622. package/examples/oidc-login/.aug-spec/august/0.19.0/web/contracts.aug.md +0 -420
  623. package/examples/ownership-transfer/.aug-spec/august/0.19.0/io/contracts.aug +0 -36
  624. package/examples/ownership-transfer/.aug-spec/august/0.19.0/io/contracts.aug.md +0 -316
  625. /package/examples/oidc-login/.aug-spec/{august/0.19.0/memory → packages/@git/url_0eb7c89453c87681ed15/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/store.aug +0 -0
  626. /package/examples/oidc-login/.aug-spec/{august/0.19.0/json → packages/@git/url_2d3c37c690c0fa115be1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
  627. /package/examples/oidc-login/.aug-spec/{august/0.19.0/web → packages/@git/url_897efafd565158fc4908/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
  628. /package/examples/oidc-login/.aug-spec/{august/0.19.0/time → packages/@git/url_c092cd151499c4e1d8a1/0.0.0-git.a39fc582565d4fca40be4f75fa304d71adc69301}/contracts.aug +0 -0
package/src/checker.js CHANGED
@@ -10,14 +10,17 @@ import { builtinType as builtin, builtinTypes, builtinProperties, collectionOper
10
10
  import { orderGraph } from "./di.js";
11
11
  import { javadocBefore } from "./javadoc.js";
12
12
  import { callableDocumentation } from "./documentation.js";
13
+ import { nativeHttpContracts } from "./http-contracts.js";
13
14
  import { jsonDataType } from "./schemas.js";
14
15
  import { htmlTags, htmlVoidTags, htmlAttribute, htmlUrlAttributes } from "./html.js";
15
16
  import { generateOpenApi } from "./openapi.js";
16
- import { httpPolicyNames, checkHttpPolicy } from "./http-policies.js";
17
+ import { httpPolicyNames, httpPolicyOptions, checkHttpPolicy } from "./http-policies.js";
18
+ import { nativeDeclarations } from "./native-declarations.js";
17
19
  export { tyName } from "./types.js";
18
20
  const builtinNames = new Set(Object.keys(builtinTypes));
19
21
  const errorTy = { id: 'error', name: '<error>', kind: 'error', args: [], nullable: false };
20
22
  const nullTy = { id: 'null', name: 'null', kind: 'null', args: [], nullable: true };
23
+ const unresolved = (type) => type.kind === 'error' || type.args.some(unresolved);
21
24
  export function checkProject(project) {
22
25
  const checker = new Checker(project);
23
26
  const checked = checker.check();
@@ -34,11 +37,17 @@ class Checker {
34
37
  bindings = [];
35
38
  interceptorPlans = new Map();
36
39
  effectContracts = new Map();
40
+ callableContracts = new Map();
41
+ constructorContracts = new Map();
42
+ initializers = new Map();
43
+ inferredChanges = new Map();
44
+ contextualResults = new Set();
37
45
  expressionOrigins = new WeakMap();
38
46
  scopes = new Map();
39
47
  markupCalls = new WeakMap();
40
48
  actions = new Map();
41
49
  httpPolicies = new Map();
50
+ native;
42
51
  bindingByKey = new Map();
43
52
  constructorFreshness = new Map();
44
53
  constraintStack = new Set();
@@ -46,13 +55,35 @@ class Checker {
46
55
  inferring = false;
47
56
  inferenceChanged = false;
48
57
  changingInference = new Set();
49
- constructor(project) { this.project = project; this.diagnostics = [...project.diagnostics]; }
58
+ constructor(project) { this.project = project; this.native = nativeDeclarations(project); this.diagnostics = [...project.diagnostics, ...this.native.diagnostics]; }
50
59
  check() {
60
+ // Make inherited default bodies visible to forward calls during inference.
61
+ this.inferring = true;
62
+ for (const def of this.project.definitions.values())
63
+ if (def.node.kind === 'class') {
64
+ const methods = new Map();
65
+ const types = this.paramsFor(def.node.typeParams, def.node, def.file);
66
+ for (const ref of def.node.implements)
67
+ for (const [name, entries] of this.interfaceMethods(this.resolveType(ref, def.file, types), new Set()))
68
+ if (!def.node.methods.some(method => method.name === name)) {
69
+ const entry = entries.find(entry => entry.method.body);
70
+ if (entry)
71
+ methods.set(name, entry);
72
+ }
73
+ this.defaults.set(def.id, methods);
74
+ }
75
+ this.inferring = false;
76
+ this.inferImplementationEffects();
51
77
  for (const def of this.project.definitions.values())
52
78
  if (def.node.kind === 'interceptor')
53
79
  this.checkInterceptorShape(def);
54
80
  this.planInterceptors();
55
- this.inferImplementationEffects();
81
+ this.constructorFreshness.clear();
82
+ // Layers can add contracts to callers. Recompute after their mappings exist.
83
+ this.inferImplementationEffects(false);
84
+ for (const layers of this.interceptorPlans.values())
85
+ for (const layer of layers)
86
+ layer.errors = this.bodyErrors(layer.around, layer.definition.file, layer.types);
56
87
  for (const def of this.project.definitions.values()) {
57
88
  if (def.node.kind === 'class')
58
89
  this.checkClassShape(def);
@@ -67,12 +98,9 @@ class Checker {
67
98
  if (def.node.kind === 'function' && def.node.body)
68
99
  this.checkFunctionBody(def.node, def.file);
69
100
  if (def.node.kind === 'class') {
70
- if (initializationOf(def.node).length)
71
- this.checkFunctionBody({
72
- kind: 'function', name: def.name, typeParams: [], params: [],
73
- returns: syntheticType('void', def.node.span), returnOwnership: 'managed',
74
- throws: def.node.validationErrors ?? [], body: initializationOf(def.node), externC: false, span: def.node.span,
75
- }, def.file, def, true);
101
+ const initializer = this.initializers.get(def.node);
102
+ if (initializer)
103
+ this.checkFunctionBody(initializer, def.file, def, true);
76
104
  for (const method of def.node.methods)
77
105
  if (method.body)
78
106
  this.checkFunctionBody(method, def.file, def);
@@ -96,15 +124,32 @@ class Checker {
96
124
  returns: layer.outputType, returnOwnership: layer.around.returnOwnership,
97
125
  indices: layer.argumentIndices });
98
126
  }
99
- for (const [node] of this.interceptorPlans)
100
- if (node.annotations?.length) {
101
- const source = this.project.files.get(node.span.file)?.source ?? '';
102
- const doc = javadocBefore(source, node.annotations[0].span.start);
103
- const errors = this.effectiveErrors(node, node.span.file, this.paramsFor(node.typeParams, node, node.span.file));
104
- for (const tag of doc?.tags ?? [])
127
+ for (const def of this.project.definitions.values()) {
128
+ if (this.project.files.get(def.file)?.builtin)
129
+ continue;
130
+ const methods = def.node.kind === 'function' ? [def.node] : 'methods' in def.node ? def.node.methods : [];
131
+ for (const method of methods) {
132
+ const source = this.project.files.get(def.file)?.source ?? '';
133
+ const doc = javadocBefore(source, method.annotations?.[0]?.span.start ?? method.span.start);
134
+ const types = new Map([...this.paramsFor(def.node.typeParams, def.node, def.file), ...this.paramsFor(method.typeParams, method, def.file)]);
135
+ const errors = this.effectiveErrors(method, def.file, types);
136
+ for (const tag of doc?.tags ?? []) {
137
+ if (['return', 'returns'].includes(tag.name) && this.returnType(method, def.file, types).name === 'void')
138
+ this.report(method.span, `@${tag.name} requires a value-returning callable`, 'DOC');
105
139
  if (['throws', 'exception'].includes(tag.name) && !errors.some(error => tyName(error) === tag.value.split(/\s/)[0]))
106
- this.report(node.span, `@${tag.name} ${tag.value.split(/\s/)[0]} is absent from ${node.name}'s effective unless contract`, 'DOC');
140
+ this.report(method.span, `@${tag.name} ${tag.value.split(/\s/)[0]} is absent from ${method.name}'s effective unless contract`, 'DOC');
141
+ }
107
142
  }
143
+ if (def.node.kind === 'class' && def.node.record && def.node.validationDeclared === false) {
144
+ const source = this.project.files.get(def.file)?.source ?? '';
145
+ const doc = javadocBefore(source, def.node.span.start);
146
+ const errors = this.effectiveErrors(def.node, def.file, this.paramsFor(def.node.typeParams, def.node, def.file));
147
+ for (const tag of doc?.tags ?? [])
148
+ if (['throws', 'exception'].includes(tag.name) &&
149
+ !errors.some(error => tyName(error) === tag.value.split(/\s/)[0]))
150
+ this.report(def.node.span, `@${tag.name} ${tag.value.split(/\s/)[0]} is absent from ${def.node.name}'s inferred validation errors`, 'DOC');
151
+ }
152
+ }
108
153
  if (this.project.main) {
109
154
  const context = { file: this.project.main.path, locals: new Map(),
110
155
  returns: builtin('void'), returnOwnership: 'managed', allowedErrors: this.project.testMode ? [builtin('Error')] : [],
@@ -131,10 +176,16 @@ class Checker {
131
176
  for (const def of this.project.definitions.values())
132
177
  if (served.has(def.id) && def.node.kind === 'function' && def.node.endpoint?.path === '/__aug/actions.js')
133
178
  this.report(def.node.span, '/__aug/actions.js is reserved for HTTP action transport', 'HTTP');
179
+ for (const [node, layers] of this.interceptorPlans)
180
+ if (node.kind === 'class') {
181
+ for (const [index, layer] of layers.entries())
182
+ layer.constructorResultFresh =
183
+ layers.slice(index + 1).every(inner => this.layerReturnsFresh(inner));
184
+ }
134
185
  return { project: this.project, diagnostics: this.diagnostics, bindings: this.bindings,
135
186
  expressionTypes: this.expressionTypes, defaults: this.defaults, callPlans: this.callPlans,
136
- interceptorPlans: this.interceptorPlans, effectContracts: this.effectContracts,
137
- expressionOrigins: this.expressionOrigins, scopes: this.scopes, markupCalls: this.markupCalls, actions: this.actions, httpPolicies: this.httpPolicies };
187
+ interceptorPlans: this.interceptorPlans, effectContracts: this.effectContracts, callableContracts: this.callableContracts, constructorContracts: this.constructorContracts,
188
+ expressionOrigins: this.expressionOrigins, scopes: this.scopes, markupCalls: this.markupCalls, actions: this.actions, httpPolicies: this.httpPolicies, native: this.native };
138
189
  }
139
190
  isStatement(item) {
140
191
  return ['expr', 'assign', 'return', 'throw', 'if', 'while', 'for', 'destructure', 'match', 'try', 'unsafe', 'borrow', 'scope', 'freeze', 'serve', 'lock', 'yield'].includes(item.kind);
@@ -144,48 +195,84 @@ class Checker {
144
195
  return;
145
196
  this.diagnostics.push({ file: span.file, line: span.line, column: span.column, message, code });
146
197
  }
147
- /** Infer implementation details before comparing them with public contracts. */
148
- inferImplementationEffects() {
198
+ /** Infer body-derived contracts without changing the cached source AST. */
199
+ inferImplementationEffects(initialize = true) {
149
200
  const bodies = [];
150
201
  for (const definition of this.project.definitions.values()) {
151
202
  const node = definition.node;
203
+ if (node.kind === 'class' && initializationOf(node).length) {
204
+ if (initialize) {
205
+ const initializer = { kind: 'function', name: node.name, typeParams: [], params: [],
206
+ returns: syntheticType('void', node.span), returnOwnership: 'managed', throws: node.validationErrors ?? [],
207
+ body: initializationOf(node), externC: false, span: node.span };
208
+ const errors = (node.validationErrors ?? []).map(ref => this.resolveType(ref, definition.file, this.paramsFor(node.typeParams, node, definition.file)));
209
+ const contract = { result: builtin('void'), errors, inferredResult: false,
210
+ inferredErrors: !!node.record && node.validationDeclared === false };
211
+ this.initializers.set(node, initializer);
212
+ this.callableContracts.set(initializer, contract);
213
+ this.constructorContracts.set(node, contract);
214
+ }
215
+ bodies.push({ method: this.initializers.get(node), definition, owner: definition, initializing: true });
216
+ }
152
217
  const methods = node.kind === 'function' ? [node] : 'methods' in node ? node.methods : [];
218
+ const types = this.paramsFor(node.typeParams, node, definition.file);
153
219
  for (const method of methods) {
154
- if (!method.body || method.externC || method.uses?.length || method.name === 'drop')
155
- continue;
156
- if (node.kind !== 'class' && !isPrivateName(method.name))
157
- continue;
158
- if (node.kind === 'interface')
159
- continue;
160
- this.inferredUses.set(method, new Map());
161
- bodies.push({ method, definition, owner: node.kind === 'function' ? undefined : definition });
220
+ const eligible = !!method.body && !method.externC && method.name !== 'drop';
221
+ if (initialize) {
222
+ const params = new Map([...types, ...this.paramsFor(method.typeParams, method, definition.file)]);
223
+ this.callableContracts.set(method, {
224
+ result: eligible && method.declared?.returns === false ? errorTy : this.resolveType(method.returns, definition.file, params),
225
+ errors: method.throws.map(ref => this.resolveType(ref, definition.file, params)),
226
+ inferredResult: eligible && method.declared?.returns === false,
227
+ inferredErrors: eligible && method.declared?.errors === false,
228
+ });
229
+ if (eligible && !method.uses?.length)
230
+ this.inferredUses.set(method, new Map());
231
+ if (eligible && !method.changes?.length)
232
+ this.inferredChanges.set(method, new Set());
233
+ }
234
+ if (eligible)
235
+ bodies.push({ method, definition, owner: node.kind === 'function' ? undefined : definition });
162
236
  }
163
237
  }
164
238
  this.inferring = true;
165
239
  try {
166
- for (const { method, owner } of bodies)
167
- if (owner?.node.kind === 'class') {
240
+ for (const { method, owner, initializing } of bodies)
241
+ if (!initializing && owner?.node.kind === 'class') {
168
242
  const types = this.paramsFor(owner.node.typeParams, owner.node, owner.file);
169
243
  for (const ref of owner.node.implements) {
170
244
  const implemented = this.resolveType(ref, owner.file, types);
171
245
  for (const entry of this.interfaceMethods(implemented, new Set()).get(method.name) ?? []) {
172
246
  const contractOwner = this.project.definitions.get(entry.from);
247
+ if (initialize && this.callableContracts.get(method)?.inferredResult && !entry.method.body) {
248
+ const interfaceTypes = new Map(entry.params);
249
+ entry.method.typeParams.forEach((name, index) => {
250
+ const own = this.paramsFor(method.typeParams, method, owner.file).get(method.typeParams[index]);
251
+ if (own)
252
+ interfaceTypes.set(name, own);
253
+ });
254
+ this.callableContracts.get(method).result = this.returnType(entry.method, entry.file, interfaceTypes);
255
+ this.contextualResults.add(method);
256
+ }
173
257
  if (contractOwner?.node.kind !== 'interface' || !contractOwner.node.capability)
174
258
  continue;
175
- // Invoking a capability is itself an effect, including synchronized stores and test adapters.
259
+ // Invoking a capability is an effect even for a pure test adapter.
176
260
  const contract = this.contractFor(entry.method, entry.file, contractOwner, entry.params);
177
261
  for (const [key, effect] of contract.uses)
178
- this.inferredUses.get(method).set(key, effect);
262
+ this.inferredUses.get(method)?.set(key, effect);
179
263
  }
180
264
  }
181
265
  }
182
- // A fixed point makes forward references and recursive helper calls order independent.
183
- // Type-changing generic recursion must provide an explicit finite contract.
184
- for (let pass = 0; pass <= bodies.length; pass++) {
266
+ // Forward references and recursive calls reach the same deterministic fixed point.
267
+ for (let pass = 0; pass <= bodies.length + 1; pass++) {
268
+ this.constructorFreshness.clear();
185
269
  this.inferenceChanged = false;
186
270
  this.changingInference.clear();
187
- for (const { method, definition, owner } of bodies)
188
- this.checkFunctionBody(method, definition.file, owner);
271
+ for (const { method, definition, owner, initializing } of bodies) {
272
+ const types = this.paramsFor(owner && 'typeParams' in owner.node ? owner.node.typeParams : [], owner?.node, definition.file);
273
+ const next = owner?.node.kind === 'interceptor' && method.name === 'around' ? this.nextFor(method, definition.file, types) : undefined;
274
+ this.checkFunctionBody(method, definition.file, owner, initializing, undefined, next);
275
+ }
189
276
  if (!this.inferenceChanged)
190
277
  return;
191
278
  }
@@ -194,7 +281,39 @@ class Checker {
194
281
  this.inferring = false;
195
282
  }
196
283
  for (const method of this.changingInference)
197
- this.report(method.span, `Effect inference for ${method.name} did not reach a finite contract; declare uses on recursive generic helpers`, 'EFFECT');
284
+ this.report(method.span, `Contract inference for ${method.name} did not reach a finite contract; declare returns, uses, or unless on recursive generic helpers`, 'INFERENCE');
285
+ }
286
+ returnType(fn, file, types = new Map()) {
287
+ const contract = this.callableContracts.get(fn);
288
+ return contract ? this.substitute(contract.result, types) : this.resolveType(fn.returns, file, types);
289
+ }
290
+ bodyErrors(fn, file, types = new Map()) {
291
+ const contract = this.callableContracts.get(fn);
292
+ return contract ? contract.errors.map(type => this.substitute(type, types)) : fn.throws.map(ref => this.resolveType(ref, file, types));
293
+ }
294
+ markInference(fn) {
295
+ this.inferenceChanged = true;
296
+ this.changingInference.add(fn);
297
+ }
298
+ inferredReturn(types) {
299
+ const known = types.filter(type => type.kind !== 'error');
300
+ if (!known.length)
301
+ return types.length ? errorTy : builtin('void');
302
+ let result = known[0];
303
+ for (const type of known.slice(1)) {
304
+ if (unresolved(result) && !unresolved(type))
305
+ result = type;
306
+ else if (type.kind === 'null' && result.kind !== 'null')
307
+ result = { ...result, nullable: true, optional: true };
308
+ else if (result.kind === 'null' && type.kind !== 'null')
309
+ result = { ...type, nullable: true, optional: true };
310
+ else if (this.assignable(type, result))
311
+ continue;
312
+ else if (this.assignable(result, type))
313
+ result = type;
314
+ // Keep the first type; the final checking pass diagnoses incompatible returns.
315
+ }
316
+ return result;
198
317
  }
199
318
  checkMemberVisibility(ownerId, ownerName, name, span, context) {
200
319
  if (isPrivateName(name) && context.self?.id !== ownerId)
@@ -212,6 +331,9 @@ class Checker {
212
331
  const args = ref.args.map(arg => this.resolveType(arg, file, params, validateConstraints));
213
332
  if (ref.name !== 'Task' && args.some(arg => arg.id === 'builtin:void'))
214
333
  this.report(ref.span, 'Collections cannot contain void', 'COLLECTION');
334
+ const containsResource = (type) => type.kind === 'resource' || type.args.some(containsResource);
335
+ if (args.some(containsResource))
336
+ this.report(ref.span, 'Native resources require individual own bindings; managed collections cannot retain them', 'OWN');
215
337
  return { ...builtin(ref.name), args,
216
338
  nullable: ref.nullable, optional: ref.optional };
217
339
  }
@@ -289,8 +411,10 @@ class Checker {
289
411
  iface.extends.forEach(ref => visit(ref, 1));
290
412
  iface.methods.forEach(method => {
291
413
  method.params.forEach(param => visit(param.type, -1));
292
- visit(method.returns, 1);
293
- method.throws.forEach(ref => visit(ref, 1));
414
+ const result = this.callableContracts.get(method)?.result;
415
+ const reference = (type) => ({ name: type.name, args: type.args.map(reference), nullable: type.nullable, optional: type.optional, span: method.span });
416
+ visit(result ? reference(result) : method.returns, 1);
417
+ (this.callableContracts.get(method)?.errors.map(reference) ?? method.throws).forEach(ref => visit(ref, 1));
294
418
  });
295
419
  }
296
420
  checkFunctionSignature(fn, file, inheritedParams) {
@@ -313,7 +437,9 @@ class Checker {
313
437
  this.report(param.span, 'A resolve parameter cannot also be own or borrow', 'DI');
314
438
  this.resolveType(param.type, file, params);
315
439
  }
316
- this.resolveType(fn.returns, file, params);
440
+ this.returnType(fn, file, params);
441
+ if (this.returnType(fn, file, params).kind === 'resource' && fn.returnOwnership !== 'own')
442
+ this.report(fn.span, 'A native resource return must declare returns own', 'OWN');
317
443
  if (fn.endpoint) {
318
444
  const endpoint = fn.endpoint;
319
445
  if (!/^[A-Z]+$/.test(endpoint.method))
@@ -342,7 +468,7 @@ class Checker {
342
468
  if (param.source?.kind === 'request' && type.name !== 'HttpRequest')
343
469
  this.report(param.span, 'from request provides HttpRequest', 'HTTP');
344
470
  }
345
- const result = this.resolveType(fn.returns, file, params);
471
+ const result = this.returnType(fn, file, params);
346
472
  if (endpoint.streams) {
347
473
  if (!['ServerEvent', 'Bytes', 'Html'].includes(result.name) || result.optional || result.nullable)
348
474
  this.report(fn.span, 'An endpoint streams ServerEvent<T>, Bytes, or Html', 'HTTP');
@@ -369,22 +495,65 @@ class Checker {
369
495
  this.report(thrown.span, `Thrown type ${typeName(thrown)} must implement Error`);
370
496
  }
371
497
  if (fn.externC) {
372
- if (fn.nativePure && (fn.uses?.length || fn.changes?.length))
373
- this.report(fn.span, 'A pure native declaration cannot declare effects', 'FFI');
374
- if (fn.params.some(param => param.injected))
375
- this.report(fn.span, 'extern C declarations cannot use resolve parameters', 'FFI');
376
- if (fn.typeParams.length || fn.throws.length && !fn.valueAbi)
377
- this.report(fn.span, 'extern C functions cannot be generic or declare unless errors', 'FFI');
378
- if (fn.returnOwnership === 'own' || fn.params.some(param => param.ownership !== 'managed'))
379
- this.report(fn.span, 'extern C functions cannot transfer AugScript ownership', 'FFI');
380
- for (const type of fn.valueAbi ? [] : [...fn.params.map(p => p.type), fn.returns]) {
381
- if (!['int', 'c_int', 'float', 'bool', 'string', 'void'].includes(type.name) || type.args.length || type.nullable)
382
- this.report(type.span, `Type ${typeName(type)} is not supported at the C FFI boundary`, 'FFI');
498
+ const native = this.native.functions.get(fn);
499
+ if (native)
500
+ this.checkNativeSignature(fn, file, native);
501
+ else {
502
+ if (fn.nativePure && (fn.uses?.length || fn.changes?.length))
503
+ this.report(fn.span, 'A pure native declaration cannot declare effects', 'FFI');
504
+ if (fn.params.some(param => param.injected))
505
+ this.report(fn.span, 'extern C declarations cannot use resolve parameters', 'FFI');
506
+ if (fn.typeParams.length || fn.throws.length && !fn.valueAbi)
507
+ this.report(fn.span, 'extern C functions cannot be generic or declare unless errors', 'FFI');
508
+ if (fn.returnOwnership === 'own' || fn.params.some(param => param.ownership !== 'managed'))
509
+ this.report(fn.span, 'extern C functions cannot transfer AugScript ownership', 'FFI');
510
+ for (const type of fn.valueAbi ? [] : [...fn.params.map(p => p.type), fn.returns]) {
511
+ if (!['int', 'c_int', 'float', 'bool', 'string', 'void'].includes(type.name) || type.args.length || type.nullable)
512
+ this.report(type.span, `Type ${typeName(type)} is not supported at the C FFI boundary`, 'FFI');
513
+ }
383
514
  }
384
515
  }
385
516
  if (fn.name === 'drop' && (fn.params.length || fn.throws.length || fn.returns.name !== 'void' || fn.uses?.length))
386
517
  this.report(fn.span, 'drop must take no inputs, return void, and perform only local cleanup; external effects require an explicit method', 'EFFECT');
387
518
  }
519
+ checkNativeSignature(fn, file, binding) {
520
+ const check = (type, view, span) => {
521
+ const name = view.kind === 'i64' ? 'int' : view.kind === 'i32' ? 'c_int' : view.kind === 'f64' ? 'float' : view.kind === 'utf8' ? 'string' : view.kind === 'bytes' ? 'Bytes' : view.kind;
522
+ const valid = view.kind === 'resource' ? type.kind === 'resource' && this.native.resources.get(type.def.node)?.module + '.' + type.name === view.resource && this.native.providers.get(type.def.node) === this.native.providers.get(fn) :
523
+ view.kind === 'f64-list' || view.kind === 'utf8-list' ? type.name === 'List' && type.args.length === 1 && type.args[0].name === (view.kind === 'f64-list' ? 'float' : 'string') : type.name === name;
524
+ if (!valid || type.nullable || type.optional)
525
+ this.report(span, `Native contract expects ${view.resource ?? view.kind}, got ${tyName(type)}`, 'NATIVE_ABI');
526
+ };
527
+ if (fn.body || fn.typeParams.length || fn.params.some(p => p.injected) || fn.annotations?.length)
528
+ this.report(fn.span, 'Native ABI declarations have concrete inputs, no body, no resolve parameters, and no interceptors', 'NATIVE_ABI');
529
+ if (fn.params.length !== binding.params.length)
530
+ this.report(fn.span, 'Native parameter count differs from the binding descriptor', 'NATIVE_ABI');
531
+ fn.params.forEach((p, i) => {
532
+ const view = binding.params[i];
533
+ if (!view)
534
+ return;
535
+ if (p.name !== view.name)
536
+ this.report(p.span, 'Native parameter label differs from the binding descriptor: ' + view.name, 'NATIVE_ABI');
537
+ check(this.resolveType(p.type, file), view, p.span);
538
+ const ownership = view.kind === 'resource' ? view.ownership === 'consume' ? 'own' : view.ownership === 'borrow' ? 'borrow' : 'managed' : 'managed';
539
+ if (p.ownership !== ownership)
540
+ this.report(p.span, 'Native parameter ownership differs from its binding descriptor', 'NATIVE_ABI');
541
+ });
542
+ check(this.returnType(fn, file), binding.result, fn.returns.span);
543
+ if ((binding.result.kind === 'resource') !== (fn.returnOwnership === 'own'))
544
+ this.report(fn.span, 'Native result ownership differs from its binding descriptor', 'NATIVE_ABI');
545
+ const errors = fn.throws.map(t => this.resolveType(t, file));
546
+ if (errors.length !== (binding.error ? 1 : 0) || binding.error && errors[0]?.def?.id !== this.native.errors.get(fn)?.id)
547
+ this.report(fn.span, 'Native checked errors differ from the binding descriptor', 'NATIVE_ABI');
548
+ if (binding.error) {
549
+ const error = errors[0]?.def?.node;
550
+ if (error?.kind !== 'class' || error.typeParams.length || error.fields.length !== 2 || error.fields[0].name !== 'code' || error.fields[0].type.name !== 'int' || error.fields[1].name !== 'message' || error.fields[1].type.name !== 'string' || error.fields.some(p => p.injected || p.ownership !== 'managed' || p.type.nullable || p.type.optional || p.type.args.length) || initializationOf(error).length || error.annotations?.length)
551
+ this.report(fn.span, 'Native status errors require an Error class with int code and string message inputs and no constructor work', 'NATIVE_ABI');
552
+ }
553
+ const uses = (fn.uses ?? []).map(u => u.source + '.' + u.operation).sort(), changes = [...(fn.changes ?? [])].sort();
554
+ if (JSON.stringify(uses) !== JSON.stringify([...binding.uses].sort()) || JSON.stringify(changes) !== JSON.stringify([...binding.changes].sort()))
555
+ this.report(fn.span, 'Native effects or mutation differ from the binding descriptor', 'NATIVE_ABI');
556
+ }
388
557
  checkInterceptorShape(def) {
389
558
  const node = def.node;
390
559
  const types = this.paramsFor(node.typeParams, node, def.file);
@@ -414,7 +583,7 @@ class Checker {
414
583
  this.report(method.span, 'Declare generic parameters on the interceptor, rather than around', 'INTERCEPTOR');
415
584
  if (method.annotations?.length)
416
585
  this.report(method.span, 'Apply interceptor layers to the target declaration; around cannot be annotated', 'INTERCEPTOR');
417
- if (method.returns.name !== 'void' && canFallThrough(method.body ?? []))
586
+ if (this.returnType(method, def.file, types).name !== 'void' && canFallThrough(method.body ?? []))
418
587
  this.report(method.span, 'around must return its result or throw on every execution path', 'INTERCEPTOR');
419
588
  if (canRepeatNext(method.body ?? []))
420
589
  this.report(method.span, 'next may be called at most once on each execution path; a loop or catch path can call it again', 'NEXT');
@@ -424,8 +593,11 @@ class Checker {
424
593
  this.report(node.span, `${node.name} must define around(...)`, 'INTERCEPTOR');
425
594
  }
426
595
  nextFor(method, file, types) {
596
+ const result = this.returnType(method, file, types);
427
597
  return { params: method.params, types: method.params.map(param => this.resolveType(param.type, file, types)),
428
- returns: this.resolveType(method.returns, file, types), returnOwnership: method.returnOwnership };
598
+ returns: result.kind === 'error' && method.declared?.returns === false ?
599
+ { id: 'continuation:' + file + ':' + method.span.start, name: '<target result>', kind: 'param', args: [], nullable: false } : result,
600
+ returnOwnership: method.returnOwnership };
429
601
  }
430
602
  inferInterceptorType(ref, actual, names, types, file) {
431
603
  inferType(ref, actual, names, types, message => this.report(ref.span, message, 'GENERIC'), (name, value) => {
@@ -450,6 +622,24 @@ class Checker {
450
622
  }
451
623
  return undefined;
452
624
  }
625
+ /** The native policy ABI accepts the published capability shape across source-package identities. */
626
+ nativeWebCapability(type, name) {
627
+ const canonical = nativeHttpContracts.get(name);
628
+ const shape = (value) => {
629
+ if (Array.isArray(value))
630
+ return value.map(shape);
631
+ if (!value || typeof value !== 'object')
632
+ return value;
633
+ return Object.fromEntries(Object.entries(value).filter(([key]) => !['span', 'nameSpan', 'headerEnd'].includes(key)).map(([key, child]) => [key, shape(child)]));
634
+ };
635
+ if (!canonical || !type.def || JSON.stringify(shape(type.def.node)) !== JSON.stringify(shape(canonical)))
636
+ return false;
637
+ if (name === 'RequestLogger')
638
+ return true;
639
+ const principal = this.project.scopes.get(type.def.file)?.get('Principal');
640
+ const expected = nativeHttpContracts.get('Principal');
641
+ return !!principal && !!expected && JSON.stringify(shape(principal.node)) === JSON.stringify(shape(expected));
642
+ }
453
643
  planInterceptors() {
454
644
  const plan = (node, file, ownerTypes, inputs, output, ownership) => {
455
645
  const layers = [];
@@ -465,7 +655,7 @@ class Checker {
465
655
  const policies = this.httpPolicies.get(node) ?? [];
466
656
  if (['Cors', 'Compress'].includes(annotation.name) && policies.some(policy => policy.name === annotation.name))
467
657
  this.report(annotation.span, `${annotation.name} may appear only once on an endpoint`, 'HTTP');
468
- policies.push(checkHttpPolicy(annotation, node, this.diagnostics, (param, name) => this.resolveType(param.type, file, ownerTypes).id === `august/web/contracts.aug:${name}`));
658
+ policies.push(checkHttpPolicy(annotation, node, this.diagnostics, (param, name) => this.nativeWebCapability(this.resolveType(param.type, file, ownerTypes), name)));
469
659
  this.httpPolicies.set(node, policies);
470
660
  }
471
661
  continue;
@@ -511,7 +701,16 @@ class Checker {
511
701
  types.set(name, this.resolveType(annotation.typeArgs[index], file, ownerTypes));
512
702
  });
513
703
  const inferredNames = interceptor.typeParams.filter((_, index) => !annotation.typeArgs[index]);
514
- this.inferInterceptorType(around.returns, output, inferredNames, types, definition.file);
704
+ const inferredOutput = this.callableContracts.get(around);
705
+ if (inferredOutput?.inferredResult) {
706
+ types.set('<target result>', output);
707
+ if (inferredOutput.result.name !== '<target result>') {
708
+ const reference = (type) => ({ name: type.name, args: type.args.map(reference), nullable: type.nullable, optional: type.optional, span: around.span });
709
+ this.inferInterceptorType(reference(inferredOutput.result), output, inferredNames, types, definition.file);
710
+ }
711
+ }
712
+ else
713
+ this.inferInterceptorType(around.returns, output, inferredNames, types, definition.file);
515
714
  const argumentIndices = around.params.map(param => param.injected ? undefined :
516
715
  inputs.findIndex(input => input.name === (mapping.get(param.name) ?? param.name)));
517
716
  const inputTypes = argumentIndices.map((index, i) => index !== undefined && index >= 0 ?
@@ -548,7 +747,7 @@ class Checker {
548
747
  }
549
748
  return undefined;
550
749
  });
551
- const result = this.resolveType(around.returns, definition.file, types);
750
+ const result = this.returnType(around, definition.file, types);
552
751
  if (!this.assignable(result, output))
553
752
  this.report(annotation.span, `${interceptor.name}.around returns ${tyName(result)}; ${node.name} requires ${tyName(output)}`, 'INTERCEPTOR');
554
753
  if (around.returnOwnership !== ownership)
@@ -566,7 +765,7 @@ class Checker {
566
765
  const argumentInjectionIndices = around.params.map(param => param.injected ? injectedIndex(param.type) : undefined);
567
766
  layers.push({ annotation, definition, around, argumentIndices, argumentBindings, constructorKeys,
568
767
  types, inputTypes, outputType: output, constructorInputIndices, argumentInjectionIndices,
569
- errors: around.throws.map(ref => this.resolveType(ref, definition.file, types)) });
768
+ errors: this.bodyErrors(around, definition.file, types) });
570
769
  }
571
770
  };
572
771
  for (const def of this.project.definitions.values()) {
@@ -575,13 +774,13 @@ class Checker {
575
774
  if (node.kind === 'class')
576
775
  plan(node, def.file, types, node.fields, { id: def.id, name: def.name, kind: 'class', def, args: [...types.values()], nullable: false }, 'managed');
577
776
  if (node.kind === 'function')
578
- plan(node, def.file, types, node.params, this.resolveType(node.returns, def.file, types), node.returnOwnership);
777
+ plan(node, def.file, types, node.params, this.returnType(node, def.file, types), node.returnOwnership);
579
778
  if ('methods' in node)
580
779
  for (const method of node.methods) {
581
780
  if (node.kind === 'interceptor' && method.name === 'around')
582
781
  continue;
583
782
  const methodTypes = new Map([...types, ...this.paramsFor(method.typeParams, method, def.file)]);
584
- plan(method, def.file, methodTypes, method.params, this.resolveType(method.returns, def.file, methodTypes), method.returnOwnership);
783
+ plan(method, def.file, methodTypes, method.params, this.returnType(method, def.file, methodTypes), method.returnOwnership);
585
784
  }
586
785
  }
587
786
  }
@@ -594,8 +793,8 @@ class Checker {
594
793
  }
595
794
  effectiveErrors(node, file, types) {
596
795
  return [
597
- ...(node.kind === 'function' ? node.throws : node.validationErrors ?? []).map(ref => this.resolveType(ref, file, types)),
598
- ...(this.interceptorPlans.get(node) ?? []).flatMap(layer => layer.errors.map(type => this.substitute(type, types))),
796
+ ...(node.kind === 'function' ? this.bodyErrors(node, file, types) : (this.constructorContracts.get(node)?.errors.map(type => this.substitute(type, types)) ?? (node.validationErrors ?? []).map(ref => this.resolveType(ref, file, types)))),
797
+ ...(this.interceptorPlans.get(node) ?? []).flatMap(layer => this.bodyErrors(layer.around, layer.definition.file, new Map([...layer.types].map(([name, type]) => [name, this.substitute(type, types)])))),
599
798
  ];
600
799
  }
601
800
  checkInterceptorDependencies() {
@@ -620,6 +819,11 @@ class Checker {
620
819
  if (!cls.record && cls.implements.length === 0)
621
820
  this.report(cls.span, `${cls.name} must implement at least one interface`, 'INTERFACE');
622
821
  const params = this.paramsFor(cls.typeParams, cls, def.file);
822
+ for (const error of cls.validationErrors ?? []) {
823
+ const type = this.resolveType(error, def.file, params);
824
+ if (!this.implementsError(type))
825
+ this.report(error.span, `Thrown type ${typeName(error)} must implement Error`);
826
+ }
623
827
  this.checkVariance(cls, def.file);
624
828
  const names = new Set();
625
829
  for (const field of fieldsOf(cls)) {
@@ -627,6 +831,8 @@ class Checker {
627
831
  this.report(field.span, `Duplicate field ${field.name}`);
628
832
  names.add(field.name);
629
833
  this.resolveType(field.type, def.file, params);
834
+ if (this.resolveType(field.type, def.file, params).kind === 'resource' && field.ownership !== 'own')
835
+ this.report(field.span, 'Native resource fields require own ownership', 'OWN');
630
836
  if (cls.record && (field.mutable || field.injected || field.ownership !== 'managed'))
631
837
  this.report(field.span, 'Record fields are immutable data; dependencies and ownership belong in behavioral classes', 'RECORD');
632
838
  if (cls.record && !this.immutableData(this.resolveType(field.type, def.file, params)))
@@ -745,7 +951,7 @@ class Checker {
745
951
  param.injected === method.params[i].injected &&
746
952
  param.ownership === method.params[i].ownership &&
747
953
  equalRef(param.type, method.params[i].type)) &&
748
- equalRef(left.returns, method.returns) &&
954
+ this.sameType(this.returnType(left, leftFile, leftParams), this.returnType(method, right.file, rightParams)) &&
749
955
  left.returnOwnership === method.returnOwnership &&
750
956
  this.effectiveErrors(left, leftFile, leftParams).every(thrown => this.effectiveErrors(method, right.file, rightParams).some(allowed => this.assignable(thrown, allowed)));
751
957
  }
@@ -851,6 +1057,8 @@ class Checker {
851
1057
  continue;
852
1058
  }
853
1059
  const interfaceDef = this.project.scopes.get(item.span.file)?.get(item.key);
1060
+ if (target.node.validationErrors?.length)
1061
+ this.report(item.span, `${target.name} has a checked constructor failure; construct it explicitly and catch or propagate the error instead of binding it`, 'DI');
854
1062
  let exposedType = targetType;
855
1063
  if (interfaceDef?.node.kind === 'interface') {
856
1064
  exposedType = this.resolveType({ name: item.key, args: item.keyTypeArgs,
@@ -863,7 +1071,7 @@ class Checker {
863
1071
  else if (item.keyTypeArgs.length)
864
1072
  this.report(item.span, `Named binding ${item.key} cannot take type arguments`, 'DI');
865
1073
  const stateful = fieldsOf(target.node).some(field => field.mutable || field.ownership === 'own' || field.type.name === 'Shared') ||
866
- target.node.methods.some(method => method.changes?.some(path => path === 'self' || path.startsWith('self.')));
1074
+ target.node.methods.some(method => this.effectiveContract(method, target.file, target, new Map(target.node.typeParams.map((name, index) => [name, targetType.args[index] ?? errorTy]))).changes.some(path => path === 'self' || path.startsWith('self.')));
867
1075
  const info = { key, target, exposedType, stateful, lifetime: item.lifetime ?? (stateful ? 'fresh' : 'shared'),
868
1076
  dependencies: [], constructorKeys: [], declaration: item, requiresScope: item.lifetime === 'scoped' };
869
1077
  this.bindings.push(info);
@@ -921,9 +1129,10 @@ class Checker {
921
1129
  for (const [name, ty] of this.paramsFor(fn.typeParams, fn, file))
922
1130
  params.set(name, ty);
923
1131
  this.addBounds(params, fn, file);
924
- const context = { file, locals: new Map(), returns: this.resolveType(fn.returns, file, params),
1132
+ const context = { file, locals: new Map(), returns: this.returnType(fn, file, params),
925
1133
  returnOwnership: fn.returnOwnership,
926
- allowedErrors: fn.throws.map(type => this.resolveType(type, file, params)),
1134
+ allowedErrors: this.bodyErrors(fn, file, params),
1135
+ inferredReturns: this.inferring && this.callableContracts.get(fn)?.inferredResult && !this.contextualResults.has(fn) ? [] : undefined,
927
1136
  unsafe: false, borrowed: new Set(), initializing, types: params, next, callable: fn, owner,
928
1137
  flow: new OwnershipFlow() };
929
1138
  if (fn.endpoint?.streams) {
@@ -934,7 +1143,7 @@ class Checker {
934
1143
  context.self = { id: owner.id, name: owner.name,
935
1144
  kind: owner.node.kind === 'class' ? 'class' : owner.node.kind === 'interceptor' ? 'interceptor' : 'interface', def: owner,
936
1145
  args: [...params.values()].slice(0, owner.node.typeParams.length), nullable: false };
937
- context.locals.set('self', { type: context.self, ownership: (fn.changes ?? []).some(path => path === 'self' || path.startsWith('self.')) || initializing ? 'borrow' : 'managed', moved: false });
1146
+ context.locals.set('self', { type: context.self, ownership: this.contractFor(fn, file, owner, params).changes.some(path => path === 'self' || path.startsWith('self.')) || initializing ? 'borrow' : 'managed', moved: false });
938
1147
  if (owner.node.kind === 'class' || owner.node.kind === 'interceptor') {
939
1148
  for (const field of fieldsOf(owner.node))
940
1149
  context.locals.set(field.name, { type: { ...this.resolveType(field.type, file, params), readonly: !field.mutable }, ownership: field.ownership,
@@ -966,7 +1175,28 @@ class Checker {
966
1175
  context.effects = this.contractFor(fn, file, owner, params);
967
1176
  if ((fn.changes ?? []).some(path => path.startsWith('self')) && !owner)
968
1177
  this.report(fn.span, 'A free function has no self to change', 'EFFECT');
1178
+ for (const policy of this.httpPolicies.get(fn) ?? []) {
1179
+ const operations = Object.values(httpPolicyOptions[policy.name]).filter(spec => spec.startsWith('dependency:'));
1180
+ policy.dependencies.forEach((index, order) => {
1181
+ const param = fn.params[index];
1182
+ if (!param || !operations[order])
1183
+ return;
1184
+ const type = this.resolveType(param.type, file, params);
1185
+ const operation = operations[order].split('.')[1];
1186
+ this.requireUse(capabilityKey(type, operation), `${tyName(type)}.${operation}`, policy.annotation.span, context, { source: tyName(type), operation, span: policy.annotation.span, capability: type });
1187
+ });
1188
+ }
969
1189
  this.checkStatements(fn.body ?? [], context, fn.span);
1190
+ if (context.inferredReturns) {
1191
+ const contract = this.callableContracts.get(fn);
1192
+ const result = this.inferredReturn(context.inferredReturns);
1193
+ if (!sameType(result, contract.result)) {
1194
+ contract.result = result;
1195
+ this.markInference(fn);
1196
+ }
1197
+ }
1198
+ if (!this.inferring && unresolved(this.returnType(fn, file, params)))
1199
+ this.report(fn.span, `Cannot infer ${fn.name}'s return type; add returns T to anchor recursive or ambiguous results`, 'INFERENCE');
970
1200
  if (fn.body && context.returns.id !== 'builtin:void' &&
971
1201
  !(owner?.node.kind === 'interceptor' && fn.name === 'around') && canFallThrough(fn.body))
972
1202
  this.report(fn.span, `${fn.name} must return a value or throw on every path`, 'TYPE');
@@ -1046,16 +1276,19 @@ class Checker {
1046
1276
  report: (span, message) => this.report(span, message, 'EFFECT'),
1047
1277
  });
1048
1278
  const inferred = this.inferredUses.get(fn);
1279
+ const inferredChanges = this.inferredChanges.get(fn);
1280
+ const changes = inferredChanges ? [...inferredChanges].sort() : result.changes;
1049
1281
  if (!inferred) {
1050
- this.effectContracts.set(fn, result);
1051
- return result;
1282
+ const contract = { ...result, changes, inferredChanges: !!inferredChanges };
1283
+ this.effectContracts.set(fn, contract);
1284
+ return contract;
1052
1285
  }
1053
1286
  const uses = new Map(result.uses);
1054
1287
  for (const [key, effect] of inferred) {
1055
1288
  const capability = effect.capability && this.substitute(effect.capability, types);
1056
1289
  uses.set(capability ? capabilityKey(capability, effect.operation) : key, { ...effect, capability, source: capability ? tyName(capability) : effect.source });
1057
1290
  }
1058
- const contract = { ...result, uses, inferred: true };
1291
+ const contract = { ...result, changes, uses, inferred: true, inferredChanges: !!inferredChanges };
1059
1292
  this.effectContracts.set(fn, contract);
1060
1293
  return contract;
1061
1294
  }
@@ -1096,7 +1329,7 @@ class Checker {
1096
1329
  changes.push([fn.params[target].name, ...path].join('.'));
1097
1330
  }
1098
1331
  }
1099
- const result = { changes: [...new Set(changes)], uses, inferred: base.inferred };
1332
+ const result = { changes: [...new Set(changes)], uses, inferred: base.inferred, inferredChanges: base.inferredChanges };
1100
1333
  this.effectContracts.set(fn, result);
1101
1334
  return result;
1102
1335
  }
@@ -1126,8 +1359,16 @@ class Checker {
1126
1359
  return;
1127
1360
  const input = context.callable.params.find(param => param.name === origin);
1128
1361
  if (path.startsWith('self') || input && input.ownership !== 'own') {
1129
- if (!coversChange(context.effects?.changes ?? [], path))
1130
- this.report(span, `${context.callable.name} must declare changes ${path.startsWith('self') ? 'self' : origin}`, 'EFFECT');
1362
+ const inferred = this.inferring && this.inferredChanges.get(context.callable);
1363
+ const change = path.startsWith('self') ? 'self' : origin;
1364
+ if (inferred) {
1365
+ if (!inferred.has(change)) {
1366
+ inferred.add(change);
1367
+ this.markInference(context.callable);
1368
+ }
1369
+ }
1370
+ else if (!coversChange(context.effects?.changes ?? [], path))
1371
+ this.report(span, `${context.callable.name} must declare changes ${change}`, 'EFFECT');
1131
1372
  }
1132
1373
  }
1133
1374
  immutableData(type, seen = new Set()) {
@@ -1214,8 +1455,9 @@ class Checker {
1214
1455
  const type = this.checkExpression(stmt.value, context);
1215
1456
  if (type.id !== 'builtin:Shared')
1216
1457
  this.report(stmt.value.span, 'lock requires Shared<T>', 'CONCURRENCY');
1217
- if (context.callable && !context.effects?.uses.size && !context.effects?.changes.length)
1218
- this.report(stmt.span, 'A callable that locks shared state declares its capability operation or changes contract', 'EFFECT');
1458
+ const external = type.readonly || !!context.flow.external(this.rootName(stmt.value) ?? '');
1459
+ if (context.callable && external && !context.effects?.uses.size && !context.effects?.changes.length)
1460
+ this.report(stmt.span, 'A callable that locks external shared state declares its capability operation or changes contract', 'EFFECT');
1219
1461
  const inside = this.cloneContext(context);
1220
1462
  inside.locked = true;
1221
1463
  const origins = allocationOrigin(stmt.span);
@@ -1377,6 +1619,8 @@ class Checker {
1377
1619
  const expected = stmt.declaredType ? this.resolveType(stmt.declaredType, context.file, context.types) :
1378
1620
  stmt.target.kind === 'name' ? context.locals.get(stmt.target.name)?.declaredType ?? context.locals.get(stmt.target.name)?.type : undefined;
1379
1621
  const value = this.checkExpression(stmt.value, context, expected);
1622
+ if (value.kind === 'resource' && stmt.target.kind === 'name' && stmt.ownership !== 'own' && context.locals.get(stmt.target.name)?.origin !== 'field')
1623
+ this.report(stmt.span, 'Native resources must be held by own bindings', 'OWN');
1380
1624
  const source = stmt.value.kind === 'name' ? context.locals.get(stmt.value.name) : undefined;
1381
1625
  const origins = this.placesOf(stmt.value, context);
1382
1626
  const ownedSource = this.ownershipOf(stmt.value, context) === 'own';
@@ -1408,9 +1652,9 @@ class Checker {
1408
1652
  context.flow.declare(stmt.target.name, origins, !!value.readonly, { source: sourceName(stmt.value) });
1409
1653
  }
1410
1654
  else if (existing) {
1411
- if (existing.ownership === 'own')
1655
+ if (existing.ownership === 'own' && existing.origin !== 'field')
1412
1656
  this.report(stmt.target.span, `Reassigning owned value ${stmt.target.name} is not supported; use a new scope`, 'OWN');
1413
- if (source?.ownership === 'own')
1657
+ if (source?.ownership === 'own' && !(existing.origin === 'field' && existing.ownership === 'own'))
1414
1658
  this.report(stmt.value.span, 'Cannot copy an owned value into a managed variable', 'OWN');
1415
1659
  if (existing.origin === 'field' && existing.ownership !== 'own' &&
1416
1660
  !context.initializing && !context.borrowed.has('self') && context.locals.get('self')?.ownership !== 'borrow')
@@ -1436,6 +1680,12 @@ class Checker {
1436
1680
  existing.type = { ...declared, nullable: value.nullable, optional: value.optional, readonly: value.readonly, frozen: value.frozen };
1437
1681
  context.flow.rebind(stmt.target.name, origins, !!value.readonly, stmt.span, (span, message) => this.report(span, message, 'BORROW'), sourceName(stmt.value));
1438
1682
  existing.moved = false;
1683
+ if (existing.origin === 'field' && existing.ownership === 'own') {
1684
+ if (source?.ownership === 'own' && stmt.value.kind === 'name')
1685
+ this.moveOwnedLocal(stmt.value.name, stmt.value.span, context);
1686
+ else if (!['own', 'fresh'].includes(this.ownershipOf(stmt.value, context)))
1687
+ this.report(stmt.value.span, 'An owned field requires a new object or another owned value', 'OWN');
1688
+ }
1439
1689
  }
1440
1690
  else {
1441
1691
  if (source?.ownership === 'own')
@@ -1461,6 +1711,8 @@ class Checker {
1461
1711
  const node = object.def?.node;
1462
1712
  const fieldName = stmt.target.name;
1463
1713
  const field = node?.kind === 'class' || node?.kind === 'interceptor' ? fieldsOf(node).find(item => item.name === fieldName) : undefined;
1714
+ if (value.kind === 'resource' && field?.ownership !== 'own')
1715
+ this.report(stmt.span, 'Native resources must be held by own fields', 'OWN');
1464
1716
  if (!(context.initializing && root === 'self') && !field?.mutable)
1465
1717
  this.report(stmt.target.span, `Field ${fieldName} is read-only; declare mutable storage`, 'MUTABILITY');
1466
1718
  if (object.readonly && !(context.initializing && root === 'self'))
@@ -1494,8 +1746,9 @@ class Checker {
1494
1746
  return;
1495
1747
  }
1496
1748
  if (stmt.kind === 'return') {
1497
- const type = stmt.value ? this.checkExpression(stmt.value, context, context.returns) : builtin('void');
1498
- const declaredErrors = context.callable?.throws.map(type => this.resolveType(type, context.file, context.types)) ?? [];
1749
+ const type = stmt.value ? this.checkExpression(stmt.value, context, context.returns.kind === 'error' ? undefined : context.returns) : builtin('void');
1750
+ context.inferredReturns?.push(type);
1751
+ const declaredErrors = context.callable ? this.bodyErrors(context.callable, context.file, context.types) : [];
1499
1752
  for (const error of context.flow.pendingTaskErrors())
1500
1753
  this.checkAllowedError(error, stmt.span, { ...context, allowedErrors: declaredErrors, exceptionalFlows: undefined });
1501
1754
  if (!this.assignable(type, context.returns))
@@ -1808,29 +2061,39 @@ class Checker {
1808
2061
  if (visiting.has(node))
1809
2062
  return false;
1810
2063
  visiting.add(node);
1811
- const result = (this.interceptorPlans.get(node) ?? []).every(layer => {
1812
- const interceptor = layer.definition.node;
1813
- return returnsFresh(layer.around.body ?? [], new Set(interceptor.fields.map(field => field.name)), expr => {
1814
- if (expr.kind !== 'call' || expr.callee.kind !== 'name')
1815
- return false;
1816
- if (expr.callee.name === 'next')
1817
- return true;
1818
- const def = this.project.scopes.get(layer.definition.file)?.get(expr.callee.name);
1819
- return def?.node.kind === 'class' && this.constructorIsFresh(def.node, visiting);
1820
- });
1821
- });
2064
+ const result = (this.interceptorPlans.get(node) ?? []).every(layer => this.layerReturnsFresh(layer, visiting));
1822
2065
  visiting.delete(node);
1823
2066
  this.constructorFreshness.set(node, result);
1824
2067
  return result;
1825
2068
  }
2069
+ layerReturnsFresh(layer, visiting = new Set()) {
2070
+ const interceptor = layer.definition.node;
2071
+ return returnsFresh(layer.around.body ?? [], new Set(interceptor.fields.map(field => field.name)), expr => {
2072
+ if (expr.kind !== 'call' || expr.callee.kind !== 'name')
2073
+ return false;
2074
+ if (expr.callee.name === 'next')
2075
+ return true;
2076
+ const def = this.project.scopes.get(layer.definition.file)?.get(expr.callee.name);
2077
+ return def?.node.kind === 'class' && this.constructorIsFresh(def.node, visiting);
2078
+ });
2079
+ }
1826
2080
  checkAllowedError(type, span, context) {
1827
2081
  if (context.deferredErrors) {
1828
2082
  context.deferredErrors.push(type);
1829
2083
  return;
1830
2084
  }
1831
2085
  context.exceptionalFlows?.push({ type, flow: context.flow.clone() });
1832
- if (!context.allowedErrors.some(allowed => this.assignable(type, allowed)))
1833
- this.report(span, `Unhandled ${tyName(type)}; catch it or declare unless ${tyName(type)}`, 'THROWS');
2086
+ if (!context.allowedErrors.some(allowed => this.assignable(type, allowed))) {
2087
+ const contract = context.callable && this.inferring && this.callableContracts.get(context.callable);
2088
+ if (contract && contract.inferredErrors && type.kind !== 'error') {
2089
+ if (!contract.errors.some(error => sameType(error, type))) {
2090
+ contract.errors.push(type);
2091
+ this.markInference(context.callable);
2092
+ }
2093
+ }
2094
+ else
2095
+ this.report(span, `Unhandled ${tyName(type)}; catch it or declare unless ${tyName(type)}`, 'THROWS');
2096
+ }
1834
2097
  }
1835
2098
  checkCollection(expr, context, expected) {
1836
2099
  const name = expr.collection === 'empty' ? expected?.name === 'Set' ? 'Set' : 'Map' : expr.collection;
@@ -1959,6 +2222,8 @@ class Checker {
1959
2222
  type = { ...builtin('Task'), args: [result] };
1960
2223
  if (expr.call.kind === 'call' && context.scope) {
1961
2224
  const plan = this.callPlans.get(expr.call), task = [...allocationOrigin(expr.span)][0], scope = `tasks:${context.scope.file}:${context.scope.start}`;
2225
+ if (plan?.returnOwnership === 'own')
2226
+ this.report(expr.call.span, 'A task cannot return an owned value. Return immutable data, or create and release the owned resource inside the task.', 'CONCURRENCY');
1962
2227
  context.flow.registerTask(task, scope, errors);
1963
2228
  const captureOrigins = (origins, actual, exclusive, span) => {
1964
2229
  if (!this.isReference(actual))
@@ -2112,6 +2377,9 @@ class Checker {
2112
2377
  }
2113
2378
  else if (expr.kind === 'call') {
2114
2379
  type = this.checkCall(expr, context);
2380
+ const plan = this.callPlans.get(expr);
2381
+ if (plan)
2382
+ plan.returnOwnership = this.ownershipOf(expr, context) === 'own' ? 'own' : 'managed';
2115
2383
  }
2116
2384
  this.expressionTypes.set(expr, type);
2117
2385
  this.expressionOrigins.set(expr, this.placesOf(expr, context));
@@ -2142,14 +2410,14 @@ class Checker {
2142
2410
  this.defaults.get(def.id)?.get(name)?.method;
2143
2411
  if (method) {
2144
2412
  this.checkMemberVisibility(def.id, def.name, name, span, context);
2145
- return this.resolveType(method.returns, def.file, new Map(def.node.typeParams.map((param, i) => [param, receiver.args[i] ?? errorTy])));
2413
+ return this.returnType(method, def.file, new Map(def.node.typeParams.map((param, i) => [param, receiver.args[i] ?? errorTy])));
2146
2414
  }
2147
2415
  }
2148
2416
  if (def?.node.kind === 'interface') {
2149
2417
  const entry = this.interfaceMethods(receiver, new Set()).get(name)?.[0];
2150
2418
  if (entry) {
2151
2419
  this.checkMemberVisibility(entry.from, def.name, name, span, context);
2152
- return this.resolveType(entry.method.returns, def.file);
2420
+ return this.returnType(entry.method, entry.file, entry.params);
2153
2421
  }
2154
2422
  }
2155
2423
  this.report(span, `${tyName(receiver)} has no member ${name}`);
@@ -2424,6 +2692,7 @@ class Checker {
2424
2692
  }
2425
2693
  if (expr.callee.kind === 'name' && expr.callee.name === 'Shared') {
2426
2694
  const plan = this.planCall(expr, ['value'], 'Shared'), index = plan.sourceIndices[0];
2695
+ plan.ownerships = ['own'];
2427
2696
  const result = index === undefined ? errorTy : argTypes[index];
2428
2697
  if (index !== undefined && !['fresh', 'own'].includes(this.ownershipOf(expr.args[index], context)))
2429
2698
  this.report(expr.args[index].span, 'Shared takes a fresh value or an owned value; existing mutable aliases cannot survive the transfer', 'OWN');
@@ -2604,8 +2873,8 @@ class Checker {
2604
2873
  else if (!jsonDataType(this.project, result))
2605
2874
  this.report(expr.span, `${tyName(result)} is not JSON data; use a record or data collection`, 'JSON');
2606
2875
  if (result.def?.node.kind === 'class')
2607
- for (const error of result.def.node.validationErrors ?? [])
2608
- this.checkAllowedError(this.resolveType(error, result.def.file), expr.span, context);
2876
+ for (const error of this.effectiveErrors(result.def.node, result.def.file, new Map(result.def.node.typeParams.map((name, index) => [name, result.args[index] ?? errorTy]))))
2877
+ this.checkAllowedError(error, expr.span, context);
2609
2878
  }
2610
2879
  return this.isReference(result) ? { ...result, readonly: true, frozen: decoding || receiver.name === 'Json' } : result;
2611
2880
  }
@@ -2728,7 +2997,7 @@ class Checker {
2728
2997
  }
2729
2998
  if (fn.externC && !context.unsafe)
2730
2999
  this.report(expr.span, `Call to extern C function ${fn.name} requires unsafe { ... }`, 'FFI');
2731
- if (fn.externC && !fn.nativePure && !(fn.valueAbi && fn.uses?.length)) {
3000
+ if (fn.externC && !fn.nativePure && !this.native.functions.has(fn) && !(fn.valueAbi && fn.uses?.length)) {
2732
3001
  const native = this.project.scopes.get(fnFile)?.get(fn.name);
2733
3002
  this.requireUse(`C:${native?.id ?? fn.name}`, `C.${fn.name}`, expr.span, context);
2734
3003
  }
@@ -2797,7 +3066,7 @@ class Checker {
2797
3066
  ], (span, message) => this.report(span, message, 'BORROW'));
2798
3067
  for (const thrown of this.effectiveErrors(fn, fnFile, params))
2799
3068
  this.checkAllowedError(thrown, expr.span, context);
2800
- const result = this.resolveType(fn.returns, fnFile, params);
3069
+ const result = this.returnType(fn, fnFile, params);
2801
3070
  return this.isReference(result) && fn.returnOwnership !== 'own' && !this.functionIsFresh(fn, fnFile, owner && 'fields' in owner.node ? new Set(fieldsOf(owner.node).map(field => field.name)) : new Set()) ?
2802
3071
  { ...result, readonly: true } : result;
2803
3072
  }
@@ -2866,7 +3135,7 @@ class Checker {
2866
3135
  else if (!['own', 'fresh'].includes(this.ownershipOf(argument, context)))
2867
3136
  this.report(argument.span, 'Owned field requires a new object or owned argument', 'OWN');
2868
3137
  }
2869
- else if (this.ownershipOf(argument, context) === 'own' && param.ownership !== 'borrow')
3138
+ else if (this.ownershipOf(argument, context) === 'own' && param.ownership !== 'borrow' && this.expressionTypes.get(argument)?.kind !== 'resource')
2870
3139
  this.report(argument.span, 'Cannot copy an owned value into managed storage', 'OWN');
2871
3140
  if (param.ownership === 'borrow') {
2872
3141
  if (context.flow.hasTaskCapture(this.placesOf(argument, context)))