worldvm 0.0.0-stage → 0.1.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 (426) hide show
  1. package/AUTHORING.md +833 -0
  2. package/README.md +154 -2
  3. package/bin/worldvm.mjs +3 -0
  4. package/dist/_internal/forma/index.d.ts +1 -0
  5. package/dist/_internal/forma/index.js +1 -0
  6. package/dist/_internal/forma/world/authoring-help.d.ts +25 -0
  7. package/dist/_internal/forma/world/authoring-help.js +130 -0
  8. package/dist/_internal/forma/world/citations.d.ts +3 -0
  9. package/dist/_internal/forma/world/citations.js +26 -0
  10. package/dist/_internal/forma/world/clock-bindings.d.ts +4 -0
  11. package/dist/_internal/forma/world/clock-bindings.js +45 -0
  12. package/dist/_internal/forma/world/compile.d.ts +13 -0
  13. package/dist/_internal/forma/world/compile.js +190 -0
  14. package/dist/_internal/forma/world/coverage.d.ts +10 -0
  15. package/dist/_internal/forma/world/coverage.js +242 -0
  16. package/dist/_internal/forma/world/digest.d.ts +1 -0
  17. package/dist/_internal/forma/world/digest.js +1 -0
  18. package/dist/_internal/forma/world/documentation.d.ts +3 -0
  19. package/dist/_internal/forma/world/documentation.js +38 -0
  20. package/dist/_internal/forma/world/homes.d.ts +4 -0
  21. package/dist/_internal/forma/world/homes.js +202 -0
  22. package/dist/_internal/forma/world/index.d.ts +6 -0
  23. package/dist/_internal/forma/world/index.js +5 -0
  24. package/dist/_internal/forma/world/lowering/accounts.d.ts +4 -0
  25. package/dist/_internal/forma/world/lowering/accounts.js +36 -0
  26. package/dist/_internal/forma/world/lowering/action-policy.d.ts +5 -0
  27. package/dist/_internal/forma/world/lowering/action-policy.js +16 -0
  28. package/dist/_internal/forma/world/lowering/agents.d.ts +6 -0
  29. package/dist/_internal/forma/world/lowering/agents.js +116 -0
  30. package/dist/_internal/forma/world/lowering/bundles.d.ts +3 -0
  31. package/dist/_internal/forma/world/lowering/bundles.js +13 -0
  32. package/dist/_internal/forma/world/lowering/child-parameters.d.ts +14 -0
  33. package/dist/_internal/forma/world/lowering/child-parameters.js +36 -0
  34. package/dist/_internal/forma/world/lowering/collects.d.ts +3 -0
  35. package/dist/_internal/forma/world/lowering/collects.js +51 -0
  36. package/dist/_internal/forma/world/lowering/component-operations.d.ts +6 -0
  37. package/dist/_internal/forma/world/lowering/component-operations.js +26 -0
  38. package/dist/_internal/forma/world/lowering/components.d.ts +7 -0
  39. package/dist/_internal/forma/world/lowering/components.js +236 -0
  40. package/dist/_internal/forma/world/lowering/connectors.d.ts +4 -0
  41. package/dist/_internal/forma/world/lowering/connectors.js +31 -0
  42. package/dist/_internal/forma/world/lowering/context.d.ts +80 -0
  43. package/dist/_internal/forma/world/lowering/context.js +316 -0
  44. package/dist/_internal/forma/world/lowering/contracts.d.ts +7 -0
  45. package/dist/_internal/forma/world/lowering/contracts.js +73 -0
  46. package/dist/_internal/forma/world/lowering/decisions.d.ts +3 -0
  47. package/dist/_internal/forma/world/lowering/decisions.js +164 -0
  48. package/dist/_internal/forma/world/lowering/derives.d.ts +3 -0
  49. package/dist/_internal/forma/world/lowering/derives.js +22 -0
  50. package/dist/_internal/forma/world/lowering/discretionary.d.ts +7 -0
  51. package/dist/_internal/forma/world/lowering/discretionary.js +15 -0
  52. package/dist/_internal/forma/world/lowering/documents.d.ts +3 -0
  53. package/dist/_internal/forma/world/lowering/documents.js +68 -0
  54. package/dist/_internal/forma/world/lowering/effective.d.ts +5 -0
  55. package/dist/_internal/forma/world/lowering/effective.js +26 -0
  56. package/dist/_internal/forma/world/lowering/entities.d.ts +3 -0
  57. package/dist/_internal/forma/world/lowering/entities.js +43 -0
  58. package/dist/_internal/forma/world/lowering/escalations.d.ts +6 -0
  59. package/dist/_internal/forma/world/lowering/escalations.js +31 -0
  60. package/dist/_internal/forma/world/lowering/evidence.d.ts +3 -0
  61. package/dist/_internal/forma/world/lowering/evidence.js +75 -0
  62. package/dist/_internal/forma/world/lowering/files.d.ts +4 -0
  63. package/dist/_internal/forma/world/lowering/files.js +56 -0
  64. package/dist/_internal/forma/world/lowering/holds.d.ts +6 -0
  65. package/dist/_internal/forma/world/lowering/holds.js +35 -0
  66. package/dist/_internal/forma/world/lowering/index.d.ts +89 -0
  67. package/dist/_internal/forma/world/lowering/index.js +115 -0
  68. package/dist/_internal/forma/world/lowering/interactions.d.ts +7 -0
  69. package/dist/_internal/forma/world/lowering/interactions.js +190 -0
  70. package/dist/_internal/forma/world/lowering/library.d.ts +5 -0
  71. package/dist/_internal/forma/world/lowering/library.js +41 -0
  72. package/dist/_internal/forma/world/lowering/milestones.d.ts +6 -0
  73. package/dist/_internal/forma/world/lowering/milestones.js +17 -0
  74. package/dist/_internal/forma/world/lowering/notices.d.ts +3 -0
  75. package/dist/_internal/forma/world/lowering/notices.js +33 -0
  76. package/dist/_internal/forma/world/lowering/param-bounds.d.ts +15 -0
  77. package/dist/_internal/forma/world/lowering/param-bounds.js +71 -0
  78. package/dist/_internal/forma/world/lowering/policies.d.ts +6 -0
  79. package/dist/_internal/forma/world/lowering/policies.js +95 -0
  80. package/dist/_internal/forma/world/lowering/principals.d.ts +62 -0
  81. package/dist/_internal/forma/world/lowering/principals.js +32 -0
  82. package/dist/_internal/forma/world/lowering/recurrences.d.ts +9 -0
  83. package/dist/_internal/forma/world/lowering/recurrences.js +56 -0
  84. package/dist/_internal/forma/world/lowering/renewal.d.ts +5 -0
  85. package/dist/_internal/forma/world/lowering/renewal.js +21 -0
  86. package/dist/_internal/forma/world/lowering/resources.d.ts +6 -0
  87. package/dist/_internal/forma/world/lowering/resources.js +19 -0
  88. package/dist/_internal/forma/world/lowering/reuse.d.ts +5 -0
  89. package/dist/_internal/forma/world/lowering/reuse.js +75 -0
  90. package/dist/_internal/forma/world/lowering/sources.d.ts +10 -0
  91. package/dist/_internal/forma/world/lowering/sources.js +47 -0
  92. package/dist/_internal/forma/world/lowering/syntax.d.ts +84 -0
  93. package/dist/_internal/forma/world/lowering/syntax.js +94 -0
  94. package/dist/_internal/forma/world/lowering/vaults.d.ts +11 -0
  95. package/dist/_internal/forma/world/lowering/vaults.js +148 -0
  96. package/dist/_internal/forma/world/prelude.generated.d.ts +1 -0
  97. package/dist/_internal/forma/world/prelude.generated.js +2 -0
  98. package/dist/_internal/forma/world/properties.d.ts +9 -0
  99. package/dist/_internal/forma/world/properties.js +387 -0
  100. package/dist/_internal/forma/world/scenarios.d.ts +10 -0
  101. package/dist/_internal/forma/world/scenarios.js +757 -0
  102. package/dist/_internal/forma/world/sensitivity.d.ts +3 -0
  103. package/dist/_internal/forma/world/sensitivity.js +118 -0
  104. package/dist/_internal/forma/world/source-syntax.d.ts +6 -0
  105. package/dist/_internal/forma/world/source-syntax.js +27 -0
  106. package/dist/_internal/forma/world/status-handling.d.ts +3 -0
  107. package/dist/_internal/forma/world/status-handling.js +143 -0
  108. package/dist/_internal/forma/world/surface.d.ts +30 -0
  109. package/dist/_internal/forma/world/surface.js +213 -0
  110. package/dist/_internal/forma/world/table-expressions.d.ts +3 -0
  111. package/dist/_internal/forma/world/table-expressions.js +41 -0
  112. package/dist/_internal/forma-tools/index.d.ts +17 -0
  113. package/dist/_internal/forma-tools/index.js +124 -0
  114. package/dist/_internal/ir-checks/advances.d.ts +7 -0
  115. package/dist/_internal/ir-checks/advances.js +6 -0
  116. package/dist/_internal/ir-checks/agent-reads.d.ts +14 -0
  117. package/dist/_internal/ir-checks/agent-reads.js +118 -0
  118. package/dist/_internal/ir-checks/amendments.d.ts +3 -0
  119. package/dist/_internal/ir-checks/amendments.js +21 -0
  120. package/dist/_internal/ir-checks/canonical-json.d.ts +3 -0
  121. package/dist/_internal/ir-checks/canonical-json.js +85 -0
  122. package/dist/_internal/ir-checks/child-parameters.d.ts +2 -0
  123. package/dist/_internal/ir-checks/child-parameters.js +43 -0
  124. package/dist/_internal/ir-checks/clock-bindings.d.ts +3 -0
  125. package/dist/_internal/ir-checks/clock-bindings.js +43 -0
  126. package/dist/_internal/ir-checks/collect-types.d.ts +14 -0
  127. package/dist/_internal/ir-checks/collect-types.js +34 -0
  128. package/dist/_internal/ir-checks/component-operations.d.ts +4 -0
  129. package/dist/_internal/ir-checks/component-operations.js +23 -0
  130. package/dist/_internal/ir-checks/content-digest.d.ts +4 -0
  131. package/dist/_internal/ir-checks/content-digest.js +78 -0
  132. package/dist/_internal/ir-checks/contract-validation.d.ts +3 -0
  133. package/dist/_internal/ir-checks/contract-validation.js +307 -0
  134. package/dist/_internal/ir-checks/contracts.d.ts +25 -0
  135. package/dist/_internal/ir-checks/contracts.js +80 -0
  136. package/dist/_internal/ir-checks/dates.d.ts +2 -0
  137. package/dist/_internal/ir-checks/dates.js +7 -0
  138. package/dist/_internal/ir-checks/documents.d.ts +3 -0
  139. package/dist/_internal/ir-checks/documents.js +45 -0
  140. package/dist/_internal/ir-checks/evidence.d.ts +20 -0
  141. package/dist/_internal/ir-checks/evidence.js +56 -0
  142. package/dist/_internal/ir-checks/files.d.ts +7 -0
  143. package/dist/_internal/ir-checks/files.js +47 -0
  144. package/dist/_internal/ir-checks/index.d.ts +59 -0
  145. package/dist/_internal/ir-checks/index.js +166 -0
  146. package/dist/_internal/ir-checks/instants.d.ts +7 -0
  147. package/dist/_internal/ir-checks/instants.js +61 -0
  148. package/dist/_internal/ir-checks/notices.d.ts +4 -0
  149. package/dist/_internal/ir-checks/notices.js +58 -0
  150. package/dist/_internal/ir-checks/policy-bounds.d.ts +5 -0
  151. package/dist/_internal/ir-checks/policy-bounds.js +28 -0
  152. package/dist/_internal/ir-checks/principals.d.ts +26 -0
  153. package/dist/_internal/ir-checks/principals.js +162 -0
  154. package/dist/_internal/ir-checks/prior-cycle.d.ts +41 -0
  155. package/dist/_internal/ir-checks/prior-cycle.js +21 -0
  156. package/dist/_internal/ir-checks/read-classification.d.ts +12 -0
  157. package/dist/_internal/ir-checks/read-classification.js +67 -0
  158. package/dist/_internal/ir-checks/read-types.d.ts +2 -0
  159. package/dist/_internal/ir-checks/read-types.js +40 -0
  160. package/dist/_internal/ir-checks/resource-proofs.d.ts +4 -0
  161. package/dist/_internal/ir-checks/resource-proofs.js +98 -0
  162. package/dist/_internal/ir-checks/resources.d.ts +3 -0
  163. package/dist/_internal/ir-checks/resources.js +30 -0
  164. package/dist/_internal/ir-checks/reuse.d.ts +10 -0
  165. package/dist/_internal/ir-checks/reuse.js +99 -0
  166. package/dist/_internal/ir-checks/sealing.d.ts +14 -0
  167. package/dist/_internal/ir-checks/sealing.js +123 -0
  168. package/dist/_internal/ir-checks/sensitive-flow.d.ts +4 -0
  169. package/dist/_internal/ir-checks/sensitive-flow.js +240 -0
  170. package/dist/_internal/ir-checks/sensitivity.d.ts +19 -0
  171. package/dist/_internal/ir-checks/sensitivity.js +133 -0
  172. package/dist/_internal/ir-checks/signatures.d.ts +4 -0
  173. package/dist/_internal/ir-checks/signatures.js +22 -0
  174. package/dist/_internal/ir-checks/vaults.d.ts +10 -0
  175. package/dist/_internal/ir-checks/vaults.js +140 -0
  176. package/dist/_internal/protocol/index.d.ts +1234 -0
  177. package/dist/_internal/protocol/index.js +215 -0
  178. package/dist/_internal/reconciler/action-intents.d.ts +17 -0
  179. package/dist/_internal/reconciler/action-intents.js +161 -0
  180. package/dist/_internal/reconciler/actions.d.ts +7 -0
  181. package/dist/_internal/reconciler/actions.js +134 -0
  182. package/dist/_internal/reconciler/amendments.d.ts +12 -0
  183. package/dist/_internal/reconciler/amendments.js +52 -0
  184. package/dist/_internal/reconciler/basis.d.ts +253 -0
  185. package/dist/_internal/reconciler/basis.js +16 -0
  186. package/dist/_internal/reconciler/bundles.d.ts +22 -0
  187. package/dist/_internal/reconciler/bundles.js +110 -0
  188. package/dist/_internal/reconciler/change-detection.d.ts +5 -0
  189. package/dist/_internal/reconciler/change-detection.js +82 -0
  190. package/dist/_internal/reconciler/collection-rules.d.ts +7 -0
  191. package/dist/_internal/reconciler/collection-rules.js +46 -0
  192. package/dist/_internal/reconciler/collection-state.d.ts +11 -0
  193. package/dist/_internal/reconciler/collection-state.js +62 -0
  194. package/dist/_internal/reconciler/collection-values.d.ts +5 -0
  195. package/dist/_internal/reconciler/collection-values.js +60 -0
  196. package/dist/_internal/reconciler/collections.d.ts +35 -0
  197. package/dist/_internal/reconciler/collections.js +141 -0
  198. package/dist/_internal/reconciler/commands.d.ts +60 -0
  199. package/dist/_internal/reconciler/commands.js +468 -0
  200. package/dist/_internal/reconciler/component-operations.d.ts +48 -0
  201. package/dist/_internal/reconciler/component-operations.js +256 -0
  202. package/dist/_internal/reconciler/context.d.ts +38 -0
  203. package/dist/_internal/reconciler/context.js +44 -0
  204. package/dist/_internal/reconciler/coverage.d.ts +31 -0
  205. package/dist/_internal/reconciler/coverage.js +124 -0
  206. package/dist/_internal/reconciler/dates.d.ts +38 -0
  207. package/dist/_internal/reconciler/dates.js +121 -0
  208. package/dist/_internal/reconciler/decide.d.ts +25 -0
  209. package/dist/_internal/reconciler/decide.js +263 -0
  210. package/dist/_internal/reconciler/decision-evaluation.d.ts +9 -0
  211. package/dist/_internal/reconciler/decision-evaluation.js +67 -0
  212. package/dist/_internal/reconciler/decision-records.d.ts +14 -0
  213. package/dist/_internal/reconciler/decision-records.js +77 -0
  214. package/dist/_internal/reconciler/decision-release.d.ts +3 -0
  215. package/dist/_internal/reconciler/decision-release.js +12 -0
  216. package/dist/_internal/reconciler/dependencies.d.ts +179 -0
  217. package/dist/_internal/reconciler/dependencies.js +372 -0
  218. package/dist/_internal/reconciler/discovery.d.ts +9 -0
  219. package/dist/_internal/reconciler/discovery.js +65 -0
  220. package/dist/_internal/reconciler/document-corrections.d.ts +18 -0
  221. package/dist/_internal/reconciler/document-corrections.js +59 -0
  222. package/dist/_internal/reconciler/documents.d.ts +26 -0
  223. package/dist/_internal/reconciler/documents.js +88 -0
  224. package/dist/_internal/reconciler/effective.d.ts +6 -0
  225. package/dist/_internal/reconciler/effective.js +17 -0
  226. package/dist/_internal/reconciler/escalations.d.ts +4 -0
  227. package/dist/_internal/reconciler/escalations.js +76 -0
  228. package/dist/_internal/reconciler/evaluation.d.ts +56 -0
  229. package/dist/_internal/reconciler/evaluation.js +704 -0
  230. package/dist/_internal/reconciler/evidence-authority.d.ts +6 -0
  231. package/dist/_internal/reconciler/evidence-authority.js +70 -0
  232. package/dist/_internal/reconciler/evidence-history.d.ts +5 -0
  233. package/dist/_internal/reconciler/evidence-history.js +22 -0
  234. package/dist/_internal/reconciler/evidence-validity.d.ts +17 -0
  235. package/dist/_internal/reconciler/evidence-validity.js +135 -0
  236. package/dist/_internal/reconciler/fact-validation.d.ts +5 -0
  237. package/dist/_internal/reconciler/fact-validation.js +49 -0
  238. package/dist/_internal/reconciler/files.d.ts +9 -0
  239. package/dist/_internal/reconciler/files.js +56 -0
  240. package/dist/_internal/reconciler/graph.d.ts +40 -0
  241. package/dist/_internal/reconciler/graph.js +298 -0
  242. package/dist/_internal/reconciler/holds.d.ts +6 -0
  243. package/dist/_internal/reconciler/holds.js +18 -0
  244. package/dist/_internal/reconciler/home-definitions.d.ts +11 -0
  245. package/dist/_internal/reconciler/home-definitions.js +25 -0
  246. package/dist/_internal/reconciler/homes.d.ts +6 -0
  247. package/dist/_internal/reconciler/homes.js +32 -0
  248. package/dist/_internal/reconciler/index.d.ts +42 -0
  249. package/dist/_internal/reconciler/index.js +58 -0
  250. package/dist/_internal/reconciler/instants.d.ts +17 -0
  251. package/dist/_internal/reconciler/instants.js +56 -0
  252. package/dist/_internal/reconciler/interaction-fields.d.ts +10 -0
  253. package/dist/_internal/reconciler/interaction-fields.js +30 -0
  254. package/dist/_internal/reconciler/invariants.d.ts +8 -0
  255. package/dist/_internal/reconciler/invariants.js +34 -0
  256. package/dist/_internal/reconciler/journal.d.ts +3 -0
  257. package/dist/_internal/reconciler/journal.js +4 -0
  258. package/dist/_internal/reconciler/linking.d.ts +10 -0
  259. package/dist/_internal/reconciler/linking.js +259 -0
  260. package/dist/_internal/reconciler/memory.d.ts +32 -0
  261. package/dist/_internal/reconciler/memory.js +190 -0
  262. package/dist/_internal/reconciler/milestones.d.ts +7 -0
  263. package/dist/_internal/reconciler/milestones.js +58 -0
  264. package/dist/_internal/reconciler/missing.d.ts +18 -0
  265. package/dist/_internal/reconciler/missing.js +79 -0
  266. package/dist/_internal/reconciler/model.d.ts +350 -0
  267. package/dist/_internal/reconciler/model.js +9 -0
  268. package/dist/_internal/reconciler/notices.d.ts +14 -0
  269. package/dist/_internal/reconciler/notices.js +80 -0
  270. package/dist/_internal/reconciler/occurrences.d.ts +3 -0
  271. package/dist/_internal/reconciler/occurrences.js +30 -0
  272. package/dist/_internal/reconciler/outputs.d.ts +12 -0
  273. package/dist/_internal/reconciler/outputs.js +132 -0
  274. package/dist/_internal/reconciler/parameters.d.ts +4 -0
  275. package/dist/_internal/reconciler/parameters.js +27 -0
  276. package/dist/_internal/reconciler/policies.d.ts +22 -0
  277. package/dist/_internal/reconciler/policies.js +94 -0
  278. package/dist/_internal/reconciler/policy-edits.d.ts +11 -0
  279. package/dist/_internal/reconciler/policy-edits.js +42 -0
  280. package/dist/_internal/reconciler/policy-linking.d.ts +4 -0
  281. package/dist/_internal/reconciler/policy-linking.js +104 -0
  282. package/dist/_internal/reconciler/principal-types.d.ts +2 -0
  283. package/dist/_internal/reconciler/principal-types.js +38 -0
  284. package/dist/_internal/reconciler/prior-decisions.d.ts +3 -0
  285. package/dist/_internal/reconciler/prior-decisions.js +34 -0
  286. package/dist/_internal/reconciler/projections.d.ts +4 -0
  287. package/dist/_internal/reconciler/projections.js +85 -0
  288. package/dist/_internal/reconciler/proofs.d.ts +9 -0
  289. package/dist/_internal/reconciler/proofs.js +24 -0
  290. package/dist/_internal/reconciler/properties.d.ts +25 -0
  291. package/dist/_internal/reconciler/properties.js +67 -0
  292. package/dist/_internal/reconciler/property-eval.d.ts +5 -0
  293. package/dist/_internal/reconciler/property-eval.js +101 -0
  294. package/dist/_internal/reconciler/property-generator.d.ts +9 -0
  295. package/dist/_internal/reconciler/property-generator.js +288 -0
  296. package/dist/_internal/reconciler/property-shrink.d.ts +14 -0
  297. package/dist/_internal/reconciler/property-shrink.js +183 -0
  298. package/dist/_internal/reconciler/provenance.d.ts +8 -0
  299. package/dist/_internal/reconciler/provenance.js +61 -0
  300. package/dist/_internal/reconciler/reconcile.d.ts +32 -0
  301. package/dist/_internal/reconciler/reconcile.js +164 -0
  302. package/dist/_internal/reconciler/recurrence.d.ts +9 -0
  303. package/dist/_internal/reconciler/recurrence.js +44 -0
  304. package/dist/_internal/reconciler/requirements.d.ts +5 -0
  305. package/dist/_internal/reconciler/requirements.js +331 -0
  306. package/dist/_internal/reconciler/resource-generation.d.ts +9 -0
  307. package/dist/_internal/reconciler/resource-generation.js +17 -0
  308. package/dist/_internal/reconciler/resource-scenarios.d.ts +26 -0
  309. package/dist/_internal/reconciler/resource-scenarios.js +78 -0
  310. package/dist/_internal/reconciler/resources.d.ts +24 -0
  311. package/dist/_internal/reconciler/resources.js +178 -0
  312. package/dist/_internal/reconciler/result-digest.d.ts +13 -0
  313. package/dist/_internal/reconciler/result-digest.js +66 -0
  314. package/dist/_internal/reconciler/reuse.d.ts +16 -0
  315. package/dist/_internal/reconciler/reuse.js +119 -0
  316. package/dist/_internal/reconciler/scenarios.d.ts +32 -0
  317. package/dist/_internal/reconciler/scenarios.js +442 -0
  318. package/dist/_internal/reconciler/scheduling.d.ts +9 -0
  319. package/dist/_internal/reconciler/scheduling.js +203 -0
  320. package/dist/_internal/reconciler/sha256.d.ts +1 -0
  321. package/dist/_internal/reconciler/sha256.js +1 -0
  322. package/dist/_internal/reconciler/signatures.d.ts +13 -0
  323. package/dist/_internal/reconciler/signatures.js +37 -0
  324. package/dist/_internal/reconciler/temporal.d.ts +10 -0
  325. package/dist/_internal/reconciler/temporal.js +46 -0
  326. package/dist/_internal/reconciler/upgrades.d.ts +6 -0
  327. package/dist/_internal/reconciler/upgrades.js +65 -0
  328. package/dist/_internal/reconciler/wire.d.ts +2 -0
  329. package/dist/_internal/reconciler/wire.js +5 -0
  330. package/dist/_internal/reconciler/work.d.ts +32 -0
  331. package/dist/_internal/reconciler/work.js +101 -0
  332. package/dist/_internal/world-ir/schema.generated.d.ts +180 -0
  333. package/dist/_internal/world-ir/schema.generated.js +1127 -0
  334. package/dist/_internal/world-ir/types.generated.d.ts +1011 -0
  335. package/dist/_internal/world-ir/types.generated.js +1 -0
  336. package/dist/authoring.d.ts +9 -0
  337. package/dist/authoring.js +10 -0
  338. package/dist/catalogue.d.ts +20 -0
  339. package/dist/catalogue.js +531 -0
  340. package/dist/cli.d.ts +2 -0
  341. package/dist/cli.js +553 -0
  342. package/dist/codegen.d.ts +6 -0
  343. package/dist/codegen.js +89 -0
  344. package/dist/coverage.d.ts +60 -0
  345. package/dist/coverage.js +128 -0
  346. package/dist/deploy.d.ts +21 -0
  347. package/dist/deploy.js +72 -0
  348. package/dist/diagnostics.d.ts +9 -0
  349. package/dist/diagnostics.js +37 -0
  350. package/dist/diff.d.ts +17 -0
  351. package/dist/diff.js +19 -0
  352. package/dist/durable-object.d.ts +14 -0
  353. package/dist/durable-object.js +30 -0
  354. package/dist/explain.d.ts +113 -0
  355. package/dist/explain.js +225 -0
  356. package/dist/fixes.d.ts +4 -0
  357. package/dist/fixes.js +70 -0
  358. package/dist/fmt.d.ts +12 -0
  359. package/dist/fmt.js +39 -0
  360. package/dist/handle/open.d.ts +18 -0
  361. package/dist/handle/open.js +28 -0
  362. package/dist/handle/protocol.d.ts +12 -0
  363. package/dist/handle/protocol.js +96 -0
  364. package/dist/handle/store.d.ts +31 -0
  365. package/dist/handle/store.js +11 -0
  366. package/dist/handle/types.d.ts +37 -0
  367. package/dist/handle/types.js +1 -0
  368. package/dist/handle/world.d.ts +190 -0
  369. package/dist/handle/world.js +533 -0
  370. package/dist/http.d.ts +3 -0
  371. package/dist/http.js +72 -0
  372. package/dist/impact.d.ts +21 -0
  373. package/dist/impact.js +57 -0
  374. package/dist/index.d.ts +30 -0
  375. package/dist/index.js +43 -0
  376. package/dist/init.d.ts +13 -0
  377. package/dist/init.js +99 -0
  378. package/dist/ir-schema.json +4213 -0
  379. package/dist/lints.d.ts +8 -0
  380. package/dist/lints.js +154 -0
  381. package/dist/lsp.d.ts +14 -0
  382. package/dist/lsp.js +380 -0
  383. package/dist/manual/catalog.d.ts +12 -0
  384. package/dist/manual/catalog.js +23 -0
  385. package/dist/manual/examples.d.ts +15 -0
  386. package/dist/manual/examples.js +39 -0
  387. package/dist/manual/projections.d.ts +77 -0
  388. package/dist/manual/projections.js +344 -0
  389. package/dist/manual/prose.d.ts +19 -0
  390. package/dist/manual/prose.js +215 -0
  391. package/dist/manual/render.d.ts +76 -0
  392. package/dist/manual/render.js +250 -0
  393. package/dist/manual/text.d.ts +7 -0
  394. package/dist/manual/text.js +15 -0
  395. package/dist/mcp.d.ts +32 -0
  396. package/dist/mcp.js +269 -0
  397. package/dist/mutate.d.ts +36 -0
  398. package/dist/mutate.js +123 -0
  399. package/dist/project.d.ts +26 -0
  400. package/dist/project.js +80 -0
  401. package/dist/refine.d.ts +18 -0
  402. package/dist/refine.js +197 -0
  403. package/dist/release/diff.d.ts +45 -0
  404. package/dist/release/diff.js +103 -0
  405. package/dist/release/impact.d.ts +83 -0
  406. package/dist/release/impact.js +214 -0
  407. package/dist/release/nodes.d.ts +20 -0
  408. package/dist/release/nodes.js +118 -0
  409. package/dist/render.d.ts +19 -0
  410. package/dist/render.js +43 -0
  411. package/dist/serve.d.ts +18 -0
  412. package/dist/serve.js +140 -0
  413. package/dist/snapshot.d.ts +19 -0
  414. package/dist/snapshot.js +45 -0
  415. package/dist/sqlite.d.ts +16 -0
  416. package/dist/sqlite.js +151 -0
  417. package/dist/test.d.ts +54 -0
  418. package/dist/test.js +131 -0
  419. package/dist/world.d.ts +7 -0
  420. package/dist/world.js +5 -0
  421. package/docs/authoring/vendor-risk/example.forma +11 -0
  422. package/docs/authoring/vendor-risk/library/vendor.forma +76 -0
  423. package/docs/authoring/vendor-risk/scenarios/reviews.forma +107 -0
  424. package/docs/protocol.md +195 -0
  425. package/docs/reference.md +258 -0
  426. package/package.json +81 -3
@@ -0,0 +1,8 @@
1
+ import type { WorldIR } from "./_internal/forma/world/index.js";
2
+ import type { CliDiagnostic } from "./project.js";
3
+ import type { SourceText } from "./refine.js";
4
+ /**
5
+ * Authoring lints for silent semantic traps. They run in the CLI only, never in the
6
+ * compiler, so compiled IR and lab goldens are unaffected.
7
+ */
8
+ export declare const authoringLints: (ir: WorldIR, files: readonly SourceText[]) => CliDiagnostic[];
package/dist/lints.js ADDED
@@ -0,0 +1,154 @@
1
+ import { catalogueEntry } from "./catalogue.js";
2
+ /** Every expression a component or decision evaluates, with its owning component. */
3
+ const roots = (ir) => {
4
+ const out = [];
5
+ const add = (component, expr, conjunctive = false) => {
6
+ if (expr)
7
+ out.push({ component, expr, conjunctive });
8
+ };
9
+ for (const c of ir.components) {
10
+ for (const r of c.requirements) {
11
+ add(c.name, r.appliesWhen);
12
+ add(c.name, r.satisfiedBy);
13
+ add(c.name, r.due);
14
+ }
15
+ for (const a of c.actions)
16
+ for (const n of a.needs)
17
+ add(c.name, n.expr, true);
18
+ for (const i of c.invariants)
19
+ add(c.name, i.while);
20
+ for (const m of c.milestones ?? [])
21
+ add(c.name, m.when);
22
+ for (const h of c.holds ?? [])
23
+ add(c.name, h.while);
24
+ }
25
+ for (const d of ir.decisions ?? [])
26
+ add(d.of, d.when);
27
+ return out;
28
+ };
29
+ const sourceOf = (files, at) => files.find((f) => f.id === at.src)?.text.slice(at.from, at.to);
30
+ /**
31
+ * A requirement nobody can advance that applies when a fact has a particular value only
32
+ * detects that state. Suggest the invariant that would reject the labelled write instead.
33
+ */
34
+ const detectOnly = (ir, files) => {
35
+ const out = [];
36
+ for (const c of ir.components) {
37
+ if (c.invariants.length)
38
+ continue;
39
+ const advanced = new Set(c.actions.flatMap((a) => (Array.isArray(a.advances) ? a.advances : [a.advances])));
40
+ for (const r of c.requirements) {
41
+ if (advanced.has(r.name) || !r.appliesWhen)
42
+ continue;
43
+ let found;
44
+ visit(r.appliesWhen, (call) => {
45
+ if (found || call.fn !== "=" || call.args.length !== 2)
46
+ return;
47
+ const fact = call.args.find((a) => a.k === "attr" || a.k === "read");
48
+ const kw = call.args.find((a) => a.k === "kw");
49
+ if (fact?.meta?.path && kw?.v)
50
+ found = { path: fact.meta.path, value: kw.v };
51
+ });
52
+ if (!found)
53
+ continue;
54
+ const [subject, ...fields] = found.path.split(".");
55
+ const guard = sourceOf(files, r.satisfiedBy.at) ?? "<condition>";
56
+ const kind = `set-${fields.join("-")}`;
57
+ const name = `guard-${r.name}`;
58
+ out.push({
59
+ code: "I_DETECT_ONLY",
60
+ severity: "info",
61
+ message: `${c.name}/${r.name} flags ${found.path} = :${found.value} after it is written; nothing prevents the write.`,
62
+ at: r.at,
63
+ help: `If the write should be blocked rather than flagged, add an invariant and label the write with its kind:\n (invariant ${name}\n :forbids (action-kind :${kind} :subject ${subject})\n :while (not ${guard}))\nA scenario then checks it with (set alias :${fields.join(".")} :${found.value} :kind :${kind} :subject alias :by someone) and (expect (rejected 1) :${name}). Only writes submitted as commands with that kind are checked; Unknown conditions admit the write.`,
64
+ fix: null,
65
+ });
66
+ }
67
+ }
68
+ return out;
69
+ };
70
+ /** Visit call nodes, tracking whether an all? encloses them. */
71
+ const visit = (e, f, inAll = false) => {
72
+ if (!e || typeof e !== "object")
73
+ return;
74
+ if (Array.isArray(e)) {
75
+ e.forEach((x) => visit(x, f, inAll));
76
+ return;
77
+ }
78
+ const node = e;
79
+ if (node.k === "call")
80
+ f(node, inAll);
81
+ const nested = inAll || (node.k === "call" && node.fn === "all?");
82
+ for (const [key, child] of Object.entries(node))
83
+ if (key !== "at")
84
+ visit(child, f, nested);
85
+ };
86
+ const headFix = (files, at, from, to) => {
87
+ const text = files.find((f) => f.id === at.src)?.text;
88
+ if (!text)
89
+ return null;
90
+ const m = /^\(\s*/.exec(text.slice(at.from, at.to));
91
+ if (!m)
92
+ return null;
93
+ const start = at.from + m[0].length;
94
+ return text.slice(start, start + from.length) === from
95
+ ? { src: at.src, from: start, to: start + from.length, text: to, expected: from }
96
+ : null;
97
+ };
98
+ const warning = (code, message, at, help, fix) => ({
99
+ code,
100
+ severity: "warning",
101
+ message,
102
+ at,
103
+ help: help || catalogueEntry(code).fix,
104
+ fix,
105
+ });
106
+ /** Whether every member of a local output can be NotApplicable at once. */
107
+ const mayBeNotApplicable = (component, name, seen = new Set()) => {
108
+ if (seen.has(name))
109
+ return false;
110
+ seen.add(name);
111
+ const requirement = component.requirements.find((r) => r.name === name);
112
+ if (requirement)
113
+ return !!requirement.appliesWhen;
114
+ const output = component.outputs.find((o) => o.name === name);
115
+ return (!!output?.paths.length &&
116
+ output.paths.every((p) => p.segments.length === 1 && mayBeNotApplicable(component, p.segments[0], seen)));
117
+ };
118
+ /**
119
+ * Authoring lints for silent semantic traps. They run in the CLI only, never in the
120
+ * compiler, so compiled IR and lab goldens are unaffected.
121
+ */
122
+ export const authoringLints = (ir, files) => {
123
+ const out = [];
124
+ const seen = new Set();
125
+ const components = new Map(ir.components.map((c) => [c.name, c]));
126
+ const once = (d) => {
127
+ const key = `${d.code}@${d.at?.src}:${d.at?.from}`;
128
+ if (!seen.has(key)) {
129
+ seen.add(key);
130
+ out.push(d);
131
+ }
132
+ };
133
+ for (const { component, expr, conjunctive } of roots(ir))
134
+ visit(expr, (call, inAll) => {
135
+ const arg = call.args[0];
136
+ if (call.fn === "satisfied?") {
137
+ const name = arg?.k === "var"
138
+ ? arg.name
139
+ : arg?.k === "inst" && arg.of.k === "var" && arg.of.name === "self"
140
+ ? arg.field
141
+ : undefined;
142
+ const owner = components.get(component);
143
+ const requirement = owner?.requirements.find((r) => r.name === name);
144
+ const output = owner?.outputs.find((o) => o.name === name);
145
+ const fix = headFix(files, call.at, "satisfied?", "met?");
146
+ if (requirement?.appliesWhen && (inAll || conjunctive))
147
+ once(warning("W_SATISFIED_NOT_APPLICABLE", `(satisfied? ${name}) is false whenever ${name} is NotApplicable, so this conjunction cannot hold when ${name} does not apply.`, call.at, `Use (met? ${name}) (Satisfied, Waived or NotApplicable), or group the requirements in an (output name (all-of … ${name})) and read it with (met? self.name).`, fix));
148
+ if (output && owner && mayBeNotApplicable(owner, output.name))
149
+ once(warning("W_SATISFIED_NOT_APPLICABLE", `(satisfied? ${call.args[0]?.k === "inst" ? "self." : ""}${name}) is false when every member of output ${name} is NotApplicable, because the output is then NotApplicable too.`, call.at, `all-of ignores NotApplicable members but is itself NotApplicable when all of them are. Use (met? ${call.args[0]?.k === "inst" ? "self." : ""}${name}) if "nothing applies" should count as met.`, fix));
150
+ }
151
+ }, false);
152
+ out.push(...detectOnly(ir, files));
153
+ return out;
154
+ };
package/dist/lsp.d.ts ADDED
@@ -0,0 +1,14 @@
1
+ interface Position {
2
+ line: number;
3
+ character: number;
4
+ }
5
+ export declare const positionAt: (text: string, offset: number) => Position;
6
+ /** Stateful, transport-independent LSP session. Notifications are emitted through send. */
7
+ export declare const createLspServer: (send: (message: unknown) => void) => {
8
+ handle: (message: unknown) => Promise<unknown>;
9
+ readonly exited: boolean;
10
+ readonly shutdown: boolean;
11
+ };
12
+ /** LSP uses Content-Length byte framing, unlike MCP's newline-delimited transport. */
13
+ export declare const serveLsp: (input?: NodeJS.ReadableStream, output?: NodeJS.WritableStream) => Promise<void>;
14
+ export {};
package/dist/lsp.js ADDED
@@ -0,0 +1,380 @@
1
+ import { readdir, readFile } from "node:fs/promises";
2
+ import { dirname, resolve, relative, sep } from "node:path";
3
+ import { fileURLToPath, pathToFileURL } from "node:url";
4
+ import { formatForma, readForma } from "./_internal/forma-tools/index.js";
5
+ import { TOP_LEVEL_FORMS, CHILD_FORMS, coreDiagnostics } from "./_internal/forma/world/index.js";
6
+ import { compileProject, loadProject } from "./project.js";
7
+ import { explain } from "./catalogue.js";
8
+ export const positionAt = (text, offset) => {
9
+ const before = text.slice(0, Math.max(0, Math.min(offset, text.length)));
10
+ const lines = before.split("\n");
11
+ return { line: lines.length - 1, character: lines.at(-1).length };
12
+ };
13
+ const offsetAt = (text, p) => {
14
+ const lines = text.split("\n");
15
+ return (lines.slice(0, p.line).reduce((n, line) => n + line.length + 1, 0) +
16
+ Math.min(p.character, lines[p.line]?.length ?? 0));
17
+ };
18
+ const rangeAt = (text, from, to) => ({
19
+ start: positionAt(text, from),
20
+ end: positionAt(text, to),
21
+ });
22
+ const uriFor = (project, src) => pathToFileURL(resolve(project.directory, src)).href;
23
+ const idFor = (directory, path) => relative(directory, path).split(sep).join("/");
24
+ /** A source directory is the fallback for standalone documents. Prefer the nearest ancestor
25
+ * with an account header so library/scenario subdirectories see their sibling sources.
26
+ * A library-only project uses its nearest library header. */
27
+ const projectRoot = async (path) => {
28
+ const fallback = dirname(path);
29
+ let directory = fallback;
30
+ let library = null;
31
+ while (true) {
32
+ const entries = await readdir(directory, { withFileTypes: true });
33
+ for (const entry of entries) {
34
+ if (entry.isFile() && !entry.name.startsWith(".") && entry.name.endsWith(".forma")) {
35
+ const text = await readFile(resolve(directory, entry.name), "utf8");
36
+ const heads = readForma(text)
37
+ .forms.filter((f) => f.kind === "List")
38
+ .map((f) => f.children.find((c) => c.kind !== "Comment")?.text);
39
+ if (heads.includes("account"))
40
+ return directory;
41
+ if (!library && heads.includes("library"))
42
+ library = directory;
43
+ }
44
+ }
45
+ const parent = dirname(directory);
46
+ if (parent === directory)
47
+ return library ?? fallback;
48
+ directory = parent;
49
+ }
50
+ };
51
+ const declarationKinds = new Set([
52
+ ...TOP_LEVEL_FORMS,
53
+ "requirement",
54
+ "action",
55
+ "output",
56
+ "invariant",
57
+ ]);
58
+ const declarations = (project) => {
59
+ const result = [];
60
+ for (const file of project.files) {
61
+ const visit = (nodes, owner, top) => {
62
+ for (const node of nodes) {
63
+ if (node.kind !== "List")
64
+ continue;
65
+ const atoms = node.children.filter((c) => c.kind !== "Comment");
66
+ const head = atoms[0]?.text ?? "", name = atoms[1];
67
+ if (name?.kind === "Atom" &&
68
+ !name.text.startsWith('"') &&
69
+ declarationKinds.has(head) &&
70
+ (top || owner !== null)) {
71
+ result.push({
72
+ name: name.text,
73
+ kind: head,
74
+ owner,
75
+ uri: uriFor(project, file.id),
76
+ range: rangeAt(file.text, name.from, name.to),
77
+ });
78
+ }
79
+ if (head === "component")
80
+ visit(atoms.slice(2), name?.text ?? null, false);
81
+ }
82
+ };
83
+ visit(readForma(file.text).forms, null, true);
84
+ }
85
+ return result;
86
+ };
87
+ const atomAt = (text, offset) => {
88
+ const visit = (nodes, owner) => {
89
+ for (const node of nodes) {
90
+ if (offset < node.from || offset > node.to)
91
+ continue;
92
+ if (node.kind === "Atom")
93
+ return { atom: node, owner, head: false };
94
+ if (node.kind === "Comment")
95
+ return null;
96
+ const children = node.children.filter((c) => c.kind !== "Comment");
97
+ const found = visit(node.children, children[0]?.text === "component" ? (children[1]?.text ?? owner) : owner);
98
+ if (found)
99
+ return {
100
+ ...found,
101
+ head: found.head || (node.kind === "List" && found.atom === children[0]),
102
+ };
103
+ }
104
+ return null;
105
+ };
106
+ return visit(readForma(text).forms, null);
107
+ };
108
+ /** Stateful, transport-independent LSP session. Notifications are emitted through send. */
109
+ export const createLspServer = (send) => {
110
+ const documents = new Map();
111
+ const published = new Map();
112
+ let core = false;
113
+ let shutdown = false, exited = false;
114
+ const projectFor = async (uri) => {
115
+ const path = fileURLToPath(uri), directory = await projectRoot(path);
116
+ const disk = await loadProject(directory);
117
+ const files = new Map(disk.files.map((f) => [f.id, f.text]));
118
+ for (const [openUri, doc] of documents) {
119
+ const id = idFor(directory, fileURLToPath(openUri));
120
+ if (id !== ".." && !id.startsWith("../") && id.endsWith(".forma"))
121
+ files.set(id, doc.text);
122
+ }
123
+ return compileProject(directory, [...files].sort(([a], [b]) => a.localeCompare(b)).map(([id, text]) => ({ id, text })));
124
+ };
125
+ const publish = async (uri) => {
126
+ const project = await projectFor(uri);
127
+ const uris = new Set([
128
+ uri,
129
+ ...project.files.map((f) => uriFor(project, f.id)),
130
+ ...(published.get(project.directory) ?? []),
131
+ ]);
132
+ published.set(project.directory, new Set(project.files.map((f) => uriFor(project, f.id))));
133
+ for (const target of uris) {
134
+ const file = project.files.find((f) => uriFor(project, f.id) === target);
135
+ const diagnostics = [...project.diagnostics, ...(core ? coreDiagnostics(project.files) : [])]
136
+ .filter((d) => (d.at ? uriFor(project, d.at.src) === target : target === uri))
137
+ .map((d) => ({
138
+ range: rangeAt(file?.text ?? "", d.at?.from ?? 0, d.at?.to ?? 0),
139
+ severity: { error: 1, warning: 2, info: 3 }[d.severity],
140
+ code: d.code,
141
+ source: "worldvm",
142
+ message: `${d.message}\n${d.help}`,
143
+ }));
144
+ send({
145
+ jsonrpc: "2.0",
146
+ method: "textDocument/publishDiagnostics",
147
+ params: {
148
+ uri: target,
149
+ ...(documents.has(target) ? { version: documents.get(target).version } : {}),
150
+ diagnostics,
151
+ },
152
+ });
153
+ }
154
+ };
155
+ const handle = async (message) => {
156
+ const req = message;
157
+ if (!req || req.jsonrpc !== "2.0" || typeof req.method !== "string")
158
+ return { jsonrpc: "2.0", id: null, error: { code: -32600, message: "Invalid request." } };
159
+ const reply = (result) => "id" in req ? { jsonrpc: "2.0", id: req.id, result } : null;
160
+ const error = (code, message) => "id" in req ? { jsonrpc: "2.0", id: req.id, error: { code, message } } : null;
161
+ try {
162
+ if (req.method === "exit") {
163
+ exited = true;
164
+ return null;
165
+ }
166
+ if (req.method === "initialize") {
167
+ core =
168
+ req.params
169
+ ?.initializationOptions?.core === true;
170
+ return reply({
171
+ capabilities: {
172
+ positionEncoding: "utf-16",
173
+ textDocumentSync: { openClose: true, change: 1 },
174
+ hoverProvider: true,
175
+ completionProvider: { triggerCharacters: ["(", ":", ".", "/"] },
176
+ definitionProvider: true,
177
+ codeActionProvider: true,
178
+ documentFormattingProvider: true,
179
+ },
180
+ serverInfo: { name: "worldvm", version: "0.0.0" },
181
+ });
182
+ }
183
+ if (req.method === "shutdown") {
184
+ shutdown = true;
185
+ return reply(null);
186
+ }
187
+ if (shutdown)
188
+ return error(-32600, "Server has shut down.");
189
+ if (["initialized", "$/cancelRequest", "$/setTrace"].includes(req.method))
190
+ return null;
191
+ if (![
192
+ "textDocument/didOpen",
193
+ "textDocument/didChange",
194
+ "textDocument/didClose",
195
+ "textDocument/formatting",
196
+ "textDocument/codeAction",
197
+ "textDocument/completion",
198
+ "textDocument/hover",
199
+ "textDocument/definition",
200
+ ].includes(req.method))
201
+ return error(-32601, `Unsupported method ${req.method}.`);
202
+ const params = (req.params ?? {});
203
+ const uri = params.textDocument?.uri;
204
+ if (!uri || !uri.startsWith("file:"))
205
+ return error(-32602, "Expected a file URI.");
206
+ if (req.method === "textDocument/didOpen") {
207
+ documents.set(uri, {
208
+ text: params.textDocument.text ?? "",
209
+ version: params.textDocument.version ?? 0,
210
+ });
211
+ await publish(uri);
212
+ return null;
213
+ }
214
+ if (req.method === "textDocument/didChange") {
215
+ const current = documents.get(uri), version = params.textDocument.version ?? 0;
216
+ if (!current || version <= current.version)
217
+ return null;
218
+ const changes = params.contentChanges ?? [];
219
+ if (changes.some((c) => c.range))
220
+ return error(-32602, "Only full document sync is supported.");
221
+ if (changes.length)
222
+ documents.set(uri, { text: changes.at(-1).text, version });
223
+ await publish(uri);
224
+ return null;
225
+ }
226
+ if (req.method === "textDocument/didClose") {
227
+ documents.delete(uri);
228
+ send({
229
+ jsonrpc: "2.0",
230
+ method: "textDocument/publishDiagnostics",
231
+ params: { uri, diagnostics: [] },
232
+ });
233
+ // Recompile with disk contents and refresh other open documents in the project.
234
+ const project = await projectFor(uri);
235
+ for (const openUri of documents.keys())
236
+ if (project.files.some((f) => uriFor(project, f.id) === openUri)) {
237
+ await publish(openUri);
238
+ break;
239
+ }
240
+ return null;
241
+ }
242
+ const text = documents.get(uri)?.text ?? (await readFile(fileURLToPath(uri), "utf8"));
243
+ if (req.method === "textDocument/formatting")
244
+ return reply([{ range: rangeAt(text, 0, text.length), newText: formatForma(text) }]);
245
+ const project = await projectFor(uri);
246
+ if (req.method === "textDocument/codeAction") {
247
+ const requested = params.range ?? rangeAt(text, 0, text.length);
248
+ const from = offsetAt(text, requested.start), to = offsetAt(text, requested.end);
249
+ return reply(project.diagnostics.flatMap((d) => {
250
+ if (!d.fix ||
251
+ !d.at ||
252
+ uriFor(project, d.at.src) !== uri ||
253
+ d.at.to < from ||
254
+ d.at.from > to)
255
+ return [];
256
+ const fix = d.fix, file = project.files.find((f) => f.id === fix.src);
257
+ if (!file || file.text.slice(fix.from, fix.to) !== fix.expected)
258
+ return [];
259
+ const target = uriFor(project, fix.src);
260
+ return [
261
+ {
262
+ title: `Fix ${d.code}: ${d.help}`,
263
+ kind: "quickfix",
264
+ edit: {
265
+ documentChanges: [
266
+ {
267
+ textDocument: {
268
+ uri: target,
269
+ version: documents.get(target)?.version ?? null,
270
+ },
271
+ edits: [{ range: rangeAt(file.text, fix.from, fix.to), newText: fix.text }],
272
+ },
273
+ ],
274
+ },
275
+ },
276
+ ];
277
+ }));
278
+ }
279
+ const symbols = declarations(project);
280
+ if (req.method === "textDocument/completion")
281
+ return reply([
282
+ ...[...new Set([...TOP_LEVEL_FORMS, ...[...CHILD_FORMS.values()].flat()])].map((label) => ({ label, kind: 14, detail: "Forma form" })),
283
+ ...symbols.map((d) => ({
284
+ label: d.name,
285
+ kind: 6,
286
+ detail: `${d.kind}${d.owner ? ` in ${d.owner}` : ""}`,
287
+ })),
288
+ ]);
289
+ if (!params.position)
290
+ return error(-32602, "Expected position.");
291
+ const offset = offsetAt(text, params.position);
292
+ const found = atomAt(text, offset);
293
+ if (req.method === "textDocument/hover") {
294
+ const word = found?.atom.text ??
295
+ (text.slice(0, offset).match(/[\w/-]*$/)?.[0] ?? "") +
296
+ (text.slice(offset).match(/^[\w/-]*/)?.[0] ?? "");
297
+ const entry = explain(word);
298
+ const parents = [...CHILD_FORMS]
299
+ .filter(([, children]) => children.includes(word))
300
+ .map(([parent]) => parent);
301
+ const form = TOP_LEVEL_FORMS.includes(word)
302
+ ? `Top-level Forma form: (${word} …).`
303
+ : parents.length
304
+ ? `Forma child form: (${word} …), inside ${parents.join(", ")}.`
305
+ : null;
306
+ return reply(entry || form
307
+ ? {
308
+ contents: { kind: "plaintext", value: entry ?? form },
309
+ ...(found ? { range: rangeAt(text, found.atom.from, found.atom.to) } : {}),
310
+ }
311
+ : null);
312
+ }
313
+ if (req.method === "textDocument/definition") {
314
+ if (!found || found.head || found.atom.text.startsWith('"'))
315
+ return reply(null);
316
+ const name = found.atom.text.replace(/^self\./, "");
317
+ const candidates = symbols.filter((d) => d.name === name ||
318
+ `${d.owner}/${d.name}` === name ||
319
+ name.endsWith(`/${d.name}`) ||
320
+ name === `${d.owner}.${d.name}`);
321
+ const local = candidates.filter((d) => d.owner && d.owner === found.owner);
322
+ return reply((local.length ? local : candidates).map((d) => ({ uri: d.uri, range: d.range })));
323
+ }
324
+ return error(-32601, `Unsupported method ${req.method}.`);
325
+ }
326
+ catch (cause) {
327
+ return error(-32603, String(cause));
328
+ }
329
+ };
330
+ return {
331
+ handle,
332
+ get exited() {
333
+ return exited;
334
+ },
335
+ get shutdown() {
336
+ return shutdown;
337
+ },
338
+ };
339
+ };
340
+ /** LSP uses Content-Length byte framing, unlike MCP's newline-delimited transport. */
341
+ export const serveLsp = async (input = process.stdin, output = process.stdout) => {
342
+ const send = (message) => {
343
+ const body = JSON.stringify(message);
344
+ output.write(`Content-Length: ${Buffer.byteLength(body)}\r\n\r\n${body}`);
345
+ };
346
+ const server = createLspServer(send);
347
+ let buffer = Buffer.alloc(0);
348
+ for await (const chunk of input) {
349
+ buffer = Buffer.concat([buffer, Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)]);
350
+ while (true) {
351
+ const end = buffer.indexOf("\r\n\r\n");
352
+ if (end < 0)
353
+ break;
354
+ const length = /^Content-Length:\s*(\d+)\s*$/im.exec(buffer.subarray(0, end).toString("ascii"));
355
+ if (!length || Number(length[1]) > 16 * 1024 * 1024)
356
+ throw new Error("Invalid LSP Content-Length.");
357
+ const size = Number(length[1]);
358
+ if (buffer.length < end + 4 + size)
359
+ break;
360
+ const body = buffer.subarray(end + 4, end + 4 + size).toString("utf8");
361
+ buffer = buffer.subarray(end + 4 + size);
362
+ let message;
363
+ try {
364
+ message = JSON.parse(body);
365
+ }
366
+ catch {
367
+ send({ jsonrpc: "2.0", id: null, error: { code: -32700, message: "Parse error." } });
368
+ continue;
369
+ }
370
+ const response = await server.handle(message);
371
+ if (response !== null)
372
+ send(response);
373
+ if (server.exited) {
374
+ if (input === process.stdin && !server.shutdown)
375
+ process.exitCode = 1;
376
+ return;
377
+ }
378
+ }
379
+ }
380
+ };
@@ -0,0 +1,12 @@
1
+ import type { Component, Requirement, Span, WorldIR } from "../_internal/forma/world/index.js";
2
+ export interface RequirementCard {
3
+ readonly id: string;
4
+ readonly component: Component;
5
+ readonly requirement: Requirement;
6
+ readonly at: Span;
7
+ }
8
+ export declare const requirementCards: (ir: WorldIR) => readonly RequirementCard[];
9
+ /** Account reachability is structural, not a claim about an individual worker's applicability. */
10
+ export declare const accountComponents: (ir: WorldIR, account: string) => ReadonlySet<string>;
11
+ export declare const contains: (at: Span, src: string, offset: number) => boolean;
12
+ export declare const cardAt: (cards: readonly RequirementCard[], src: string, offset: number) => RequirementCard | undefined;
@@ -0,0 +1,23 @@
1
+ export const requirementCards = (ir) => ir.components.flatMap((component) => component.requirements.map((requirement) => ({
2
+ id: `${component.name}/${requirement.name}`,
3
+ component,
4
+ requirement,
5
+ at: requirement.at,
6
+ })));
7
+ /** Account reachability is structural, not a claim about an individual worker's applicability. */
8
+ export const accountComponents = (ir, account) => {
9
+ const names = new Set();
10
+ const visit = (name) => {
11
+ if (names.has(name))
12
+ return;
13
+ names.add(name);
14
+ for (const slot of ir.components.find((c) => c.name === name)?.slots ?? [])
15
+ visit(slot.component);
16
+ };
17
+ ir.accounts.find((a) => a.name === account)?.forEach.forEach((r) => visit(r.component));
18
+ return names;
19
+ };
20
+ export const contains = (at, src, offset) => at.src === src && at.from <= offset && offset < at.to;
21
+ export const cardAt = (cards, src, offset) => cards
22
+ .filter((c) => contains(c.at, src, offset))
23
+ .sort((a, b) => a.at.to - a.at.from - (b.at.to - b.at.from))[0];
@@ -0,0 +1,15 @@
1
+ import type { Span, WorldIR } from "../_internal/forma/world/index.js";
2
+ export interface ExampleAssertion {
3
+ readonly kind: "status" | "due";
4
+ readonly text: string;
5
+ readonly at: Span;
6
+ readonly date: string;
7
+ }
8
+ export interface RequirementExample {
9
+ readonly name: string;
10
+ readonly doc: string;
11
+ readonly at: Span;
12
+ readonly assertions: readonly ExampleAssertion[];
13
+ readonly referenceOnly: boolean;
14
+ }
15
+ export declare const requirementExamples: (ir: WorldIR, component: string, requirement: string, references: readonly string[]) => readonly RequirementExample[];
@@ -0,0 +1,39 @@
1
+ export const requirementExamples = (ir, component, requirement, references) => references
2
+ .flatMap((name) => {
3
+ const scenario = ir.scenarios?.find((s) => s.name === name);
4
+ if (!scenario)
5
+ return [];
6
+ const assertions = scenario.steps
7
+ .flatMap((step) => step.expects.flatMap((expectation) => {
8
+ if (!["status", "due"].includes(expectation.kind) ||
9
+ !("target" in expectation) ||
10
+ !("name" in expectation) ||
11
+ expectation.target.component !== component ||
12
+ expectation.name !== requirement)
13
+ return [];
14
+ const kind = expectation.kind, value = expectation.expected === null ? "unknown" : String(expectation.expected);
15
+ return [
16
+ {
17
+ kind,
18
+ text: `expect ${requirement} ${kind} ${value} · ${expectation.at.src}:${expectation.at.line}`,
19
+ at: expectation.at,
20
+ date: step.date,
21
+ },
22
+ ];
23
+ }))
24
+ .sort((a, b) => Number(b.kind === "due") - Number(a.kind === "due"));
25
+ return [
26
+ {
27
+ name,
28
+ doc: scenario.doc ?? scenario.name,
29
+ at: scenario.at,
30
+ assertions,
31
+ referenceOnly: !assertions.length,
32
+ },
33
+ ];
34
+ })
35
+ .sort((a, b) => Number(b.assertions.some((x) => x.kind === "due")) -
36
+ Number(a.assertions.some((x) => x.kind === "due")) ||
37
+ Number(a.referenceOnly) - Number(b.referenceOnly) ||
38
+ b.assertions.length - a.assertions.length ||
39
+ a.name.localeCompare(b.name));