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
package/AUTHORING.md ADDED
@@ -0,0 +1,833 @@
1
+ # Authoring worlds
2
+
3
+ This guide teaches you to write a WorldVM world from a brief: the requirements, who satisfies them
4
+ and how, where people decide, and the scenarios that prove it. Read it top to bottom once, then
5
+ use the [forms reference](#3-forms-reference), [Truth and comparisons](#4-types-truth-and-comparisons)
6
+ and the [diagnostics catalogue](#10-diagnostics-catalogue) while you work. You should not need to
7
+ read the reference worlds or the compiler to start.
8
+
9
+ Every example here is synthetic and illustrative, not legal, compliance or audit advice. Every
10
+ Forma snippet in this file is compiled by a test, and the scenarios in it pass.
11
+
12
+ Contents: [1 Layout and commands](#1-layout-and-commands) ·
13
+ [2 A minimal world](#2-a-minimal-world) · [3 Forms reference](#3-forms-reference) ·
14
+ [4 Types, Truth and comparisons](#4-types-truth-and-comparisons) · [5 Evidence](#5-evidence) ·
15
+ [6 Decisions](#6-decisions) · [7 Outputs and NotApplicable](#7-outputs-and-notapplicable) ·
16
+ [8 Actions, interactions and status changes](#8-actions-interactions-and-status-changes) ·
17
+ [9 Scenarios and properties](#9-scenarios-and-properties) ·
18
+ [10 Diagnostics catalogue](#10-diagnostics-catalogue) · [11 Units and dates](#11-units-and-dates) ·
19
+ [12 Idioms and anti-patterns](#12-idioms-and-anti-patterns) ·
20
+ [13 Recipes and a complete example](#13-recipes-and-a-complete-example)
21
+
22
+ ## 1. Layout and commands
23
+
24
+ A world is a directory of `.forma` files. The CLI reads every `.forma` file under the directory
25
+ (skipping `node_modules`, `dist`, `build`, `coverage` and dot-directories), so the split into
26
+ files is yours. A layout that scales:
27
+
28
+ ```text
29
+ my-world/
30
+ library/policy.forma ; (library …), roles, sources, evidence, interactions, components, decisions
31
+ example.forma ; entities that implement the roles, and the (account …) that runs the library
32
+ scenarios/main.forma ; (scenario …) and (property …) examples
33
+ ```
34
+
35
+ There are two halves. The **library** says what is required, of whom, and how, against abstract
36
+ **roles** (`training/worker`). The **account package** says which stored **entities** play those
37
+ roles and runs components for them with `(for-each role Component)`. Scenarios and properties
38
+ run against an account.
39
+
40
+ Install the package (`npm install worldvm effect@^4.1.1 @forma-language/forma@^0.6.0`), then
41
+ point the CLI at your directory:
42
+
43
+ ```sh
44
+ npx worldvm check my-world # compile, link accounts, report diagnostics
45
+ npx worldvm test my-world --seed 42 # run scenarios and seeded properties
46
+ npx worldvm coverage my-world # which requirements and cited clauses tests reach
47
+ npx worldvm render my-world # the human-readable manual
48
+ npx worldvm explain my-world --scenario <name> --at 2026-11-10
49
+ npx worldvm coverage my-world --mutate # semantic mutants your tests fail to catch
50
+ npx worldvm explain W_NO_SCENARIO # cause, example and fix for a diagnostic code
51
+ ```
52
+
53
+ To preview a rule change against a deployed population, export the SQLite database:
54
+
55
+ ```sh
56
+ npx worldvm deploy my-world --db world.db --account example
57
+ npx worldvm serve --db world.db
58
+ # In another terminal, or after stopping serve:
59
+ npx worldvm snapshot --db world.db --account example --out snapshot.json
60
+ npx worldvm impact my-world proposed-world --world snapshot.json --at 2026-11-10
61
+ npx worldvm explain my-world --world snapshot.json --subject hire-123 --at 2026-11-10
62
+ ```
63
+
64
+ Use the account the server opened. The export reads one committed state while the server
65
+ can keep running, and records the release that last wrote it. Omit `--out` to write JSON
66
+ to stdout. `impact` and `explain` evaluate that population at the explicit `--at` instant.
67
+
68
+ Stop `serve` before deploying changes. Use `worldvm deploy proposed-world --db world.db
69
+ --account example --dry-run --at 2026-11-10` to preview against committed records;
70
+ omit `--dry-run` to activate and retain the release. `serve <directory> --db` is a
71
+ development shortcut for deploy, then serve. A later `--clock` advances evaluation
72
+ without requiring a redeploy. See the [deployment reference](docs/reference.md#cli-impact-on-a-live-world).
73
+
74
+ Start a new world with `npx worldvm init my-world`: it writes a minimal library, account,
75
+ scenario, property and local `REFERENCE.md`. The world passes `check`, `test` and `coverage`. Every command has its own
76
+ `--help`.
77
+
78
+ Each command exits 0 when it passes and 1 when it fails; `--json` prints the machine-readable
79
+ report, where every diagnostic carries `code`, `at` (file, line, column, offsets), `help` and
80
+ `fix` (a mechanical edit with the exact text it replaces, or `null`). Warnings never fail `check`.
81
+
82
+ ### Glossary
83
+
84
+ | Term | Meaning |
85
+ | -------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
86
+ | **Subject** | The entity whose facts and work are being reconciled, such as one vendor. |
87
+ | **Home** | Internal code/IR term for that subject's ownership and routing boundary; diagnostic codes such as `E_NO_HOME` retain this spelling. |
88
+ | **Instance** | A component bound to particular key inputs, such as `(VendorReview acme)`. A subject can have several instances. |
89
+ | **Occurrence** | One evaluation of an instance, including a dated recurrence when the component repeats. |
90
+
91
+ ## 2. A minimal world
92
+
93
+ One file is enough. This world requires every worker to complete safety training and proves it
94
+ with one scenario.
95
+
96
+ ```forma world=minimal
97
+ ;; Synthetic example; illustrative, not legal or audit advice.
98
+ (library example.training "Safety training for each worker." :version "1.0" :subject training/worker)
99
+
100
+ (role training/worker "A person who must complete training." {:name String})
101
+
102
+ (source safety-policy "A synthetic internal safety policy."
103
+ :kind :policy :url "https://example.invalid/safety" :as-of "2026-11-01")
104
+
105
+ (evidence Completion "A signed training completion record." :of Training
106
+ {:course String}
107
+ (attest :signer worker :covers :all :method :otp))
108
+ (layout CompletionLayout "Record and sign the completion."
109
+ (step record "Record" (field course) (sign)))
110
+ (interaction CompletionEntry "The worker records the course they finished."
111
+ :actor worker :produces Completion :layout CompletionLayout)
112
+
113
+ (component Training "Track one worker's safety training."
114
+ :key [worker] :inputs {:worker (Id training/worker)}
115
+ (requirement completed
116
+ :cites [(safety-policy "1: every worker completes safety training")]
117
+ :satisfied-by (attested Completion))
118
+ (action complete :advances completed :assignee worker :via (interaction CompletionEntry))
119
+ (output done (all-of completed)))
120
+
121
+ (entity Person "A synthetic worker." :ns :example.person :display name
122
+ :implements {training/worker {:name name}}
123
+ {:name String})
124
+ (account example "A synthetic account." :requires {example.training "1.0"} :package example
125
+ (for-each training/worker Training))
126
+
127
+ (scenario completes "A worker completes training." :world example
128
+ (given (entity Person ana {:name "Ana"}) (actor ana))
129
+ (at "2026-11-02" (expect (status (Training ana) completed) :Open))
130
+ (do (perform (Training ana) complete :by ana :values {:course "Safety 101"}))
131
+ (at "2026-11-03" (expect (status (Training ana) done) :Satisfied)))
132
+ ```
133
+
134
+ Read it in this order:
135
+
136
+ 1. `library` names the release (`example.training` version `"1.0"`) and the role each component's
137
+ subject plays (`:subject`).
138
+ 2. `role` declares the fields components may read. Roles store nothing.
139
+ 3. `source` is the authority you cite. Every requirement and decision should `:cites` a clause;
140
+ otherwise you get `W_UNCITED`.
141
+ 4. `evidence` is a record kept exactly as signed, owned by a component (`:of Training`). `attest`
142
+ says who signs it; `worker` here is the component input of that name.
143
+ 5. `layout` and `interaction` are how a person produces that evidence.
144
+ 6. `component` is one requirement scope. `:key` says when two runs are the same (one per worker),
145
+ `:inputs` types the key. It holds `requirement`s (what must be true), `action`s (work that
146
+ advances a requirement) and `output`s (named rollups).
147
+ 7. `entity` is stored data in the account package; `:implements` maps role fields to entity
148
+ fields. `:ns` must start with the account's `:package` name.
149
+ 8. `account` requires the library release and runs `Training` for every `training/worker`.
150
+ 9. `scenario` gives synthetic entities and actors, performs work and expects statuses.
151
+
152
+ ## 3. Forms reference
153
+
154
+ The [core reference](docs/reference.md) lists syntax, complete examples and common mistakes
155
+ for the fourteen forms needed to start. `worldvm init` includes it as `REFERENCE.md`.
156
+ Options are keyword/value pairs after the docstring; field records and child forms come last.
157
+
158
+ Advanced forms (`derive`, `calendar`, `agent`, `bundle`, `collect`, `connector`, `machine`,
159
+ `document`, `notice`, `vault`, `component-contract`, `component-import`) and component children
160
+ such as `attach`, `child`, `hold`, `invariant`, `milestone`, `resource` and `retention` are
161
+ not fully documented yet; the [complete example](docs/authoring/vendor-risk/) uses several. `worldvm check` lists top-level forms when you misspell one.
162
+
163
+ Who can act: `:assignee` and `:actor` take a component input of a person role (`worker`), a field
164
+ path to one (`vendor.owner`), or `(members group-field)` for everyone in a `Group`. In `attest`,
165
+ `:signer assignee` means whoever performs the action.
166
+
167
+ **Assignees authorize interaction work.** Ordinary `perform` and live recorded-evidence commands
168
+ require the assigned person or a member of the assigned group; account policy restrictions also
169
+ apply. Attestation additionally requires the evidence's declared signer, resolved in the selected
170
+ component occurrence. To expose actions or decisions through the embedding API, list their names in the component's
171
+ `:operations [action-name decision-name]`. This selects callable operations; authority checks
172
+ still apply.
173
+
174
+ Unknown assignments/signers and mismatched identities fail closed
175
+ (`:not-assignee` in scenarios). Unsigned drafts require assignment but do not claim a signature.
176
+ Decisions separately enforce `:by` and `:distinct-from`.
177
+
178
+ Hosts authenticate identities and memberships; WorldVM checks their domain authority. The pure
179
+ in-memory `perform` API treats `by` as a trusted human ID when no `actor` is supplied (no group
180
+ memberships); it is not a public authentication boundary. Public operations require a trusted
181
+ actor. Scenario `(given (evidence ...))` records are trusted historical setup, not live commands.
182
+
183
+ Use `worldvm check . --core` to see `I_EXTENDED_FORM` information for declarations
184
+ outside the ten core forms in [the short reference](docs/reference.md). This mode
185
+ keeps the usual validation and exit status. Editors can enable it with the LSP
186
+ initialization option `core: true`; the check API takes `{ core: true }`.
187
+
188
+ ## 4. Types, Truth and comparisons
189
+
190
+ Field types: `String`, `Int`, `Float`, `Bool`, `Date`, `Instant`, `Keyword`, `Group` (a named set
191
+ of actors), `(Id Role-or-Entity)` (a reference), `(Option T)` (may be absent) and
192
+ `(Union :a :b …)` (one of these keywords, usually through `(type Name (Union …))`). Read fields
193
+ through references with dots: `contractor.sponsor.name`.
194
+
195
+ **Conditions are Truth, not Bool.** A world reads facts that may be missing, so `:applies-when`,
196
+ `:satisfied-by`, `:needs`, `:when` and `:while` are three-valued `Truth`: true, false or Unknown
197
+ (a missing fact). Use the Truth operators there:
198
+
199
+ | You mean | Requirement, action, decision (Truth) | Property (also accepted) |
200
+ | --------------- | ----------------------------------------- | ---------------------------- |
201
+ | equal | `(= a b)` | `(= a b)` |
202
+ | not equal | `(!= a b)` | `(!= a b)` |
203
+ | order | `(< a b)` `(<= a b)` `(> a b)` `(>= a b)` | same |
204
+ | not | `(not x)` | `(not x)` |
205
+ | and | `(and x y …)` | `(and x y …)` |
206
+ | or | `(or x y …)` | `(or x y …)` |
207
+ | implies | | `(implies x y)` |
208
+ | fact is present | `(known? x)` | `(known? x)`, `(unknown? x)` |
209
+ | one of | `(in? x [:a :b])` | |
210
+ | dates | `(before? a b)` `(on-or-after? a b)` | `(< a b)` and friends |
211
+
212
+ `and`, `or` and `not` use the type of their context: Kleene Truth in conditions,
213
+ ordinary Bool in properties and Bool tests. `=` and `!=` compare in either context.
214
+ A Bool fact field already reads as a condition: write `contractor.escorted` or
215
+ `(not contractor.escorted)`. `(and)` is true and `(or)` is false; in Truth
216
+ contexts `(and collection)` and `(or collection)` also fold a collection.
217
+ The retired spellings `all?`, `any?`, `negate` and `not=` are errors for one release,
218
+ with machine-applicable fixes to `and`, `or`, `not` and `!=`.
219
+
220
+ Unknown is not false. If `contractor.risk` is missing, `(!= contractor.risk :none)` is Unknown
221
+ and the requirement's status is `Unknown`, so the gap stays visible instead of silently passing.
222
+ Use `(known? x)` when you need to branch on presence.
223
+
224
+ ## 5. Evidence
225
+
226
+ Signal-driven protocols use `(machine Protocol … :signal updated …)` and a
227
+ `(connector provider … :capabilities [] :signals [updated] :owns [Protocol])`.
228
+ Declare the signal and machine ownership even for an inbound-only connector.
229
+ `component-contract` may omit `:capabilities`; it defaults to `[]`.
230
+
231
+ The rest of this guide builds one world: contractors need site access. Its library starts with
232
+ roles, a source and the evidence types.
233
+
234
+ ```forma world=site file=library/site.forma
235
+ ;; Synthetic site-access policy; illustrative, not legal or audit advice.
236
+ (library example.site-access
237
+ "Safety and insurance requirements before a contractor's badge is active."
238
+ :version "1.0" :subject site/contractor)
239
+
240
+ (type RiskLevel (Union :high :standard :none))
241
+ (type BadgeState (Union :pending :active))
242
+ (role site/person "A sponsor, site manager or badge administrator." {:name String})
243
+ (role site/contractor "A contractor with a sponsor, approver groups and a badge."
244
+ {:name String :sponsor (Id site/person) :managers Group :admins Group
245
+ :risk RiskLevel :badge BadgeState :joined Date})
246
+
247
+ (source site-policy "Synthetic site-access policy; not compliance advice."
248
+ :kind :policy :url "https://example.invalid/site-policy" :as-of "2026-11-01")
249
+
250
+ (evidence Induction "A signed safety induction; valid for twelve months from signing."
251
+ :of SiteAccess
252
+ :expires (months-after signed-on 12)
253
+ {:course String}
254
+ (attest :signer contractor :covers :all :method :otp))
255
+ (evidence InsuranceCertificate "Proof of liability insurance with its own end date."
256
+ :of SiteAccess
257
+ :expires valid-until
258
+ {:insurer String :valid-until Date}
259
+ (attest :signer contractor.sponsor :covers :all :method :otp))
260
+ (evidence HazardPermit "A signed permit for hazardous work." :of SiteAccess
261
+ {:scope String}
262
+ (attest :signer contractor.sponsor :covers :all :method :otp))
263
+ ```
264
+
265
+ What to know about evidence:
266
+
267
+ - `:of` names the component that owns it; evidence is always recorded for one occurrence of that
268
+ component. Fields are typed like role fields.
269
+ - `(rule name :when condition :requires fields)` requires filled signed fields before
270
+ attestation. The optional `:when` reads evidence fields and uses three-valued Truth:
271
+ false skips the rule, Unknown prevents attestation, and omission always applies.
272
+ `:requires` accepts `field`, `(one-of a b …)` for at least one filled field, or
273
+ `(all-of a b …)` for every listed field. Groups must be nonempty and name declared
274
+ fields. For example, `(rule documents :when (= document-choice :list-b-and-c)
275
+ :requires (all-of list-b list-c))` requires both documents for that signed choice.
276
+ The interaction layout must show required fields when the rule applies; a `one-of`
277
+ group needs a visible alternative.
278
+ - `(attest :signer who :covers :all :method :otp)` declares who signs. The signature date is the
279
+ date the record is made.
280
+ - `:expires` is a Date computed from the signed record. Write a date field (`valid-until`), or
281
+ date arithmetic over fields and `signed-on`, the date the record was signed:
282
+ `(months-after signed-on 12)`. Expiry is exclusive: a record expiring on 2027-11-07 is valid
283
+ through 2027-11-06. It may not read live facts, other evidence or decisions (`E_EXPIRES_SCOPE`).
284
+ - **`(attested E)` vs `(valid E)`.** `attested` is true once a record was ever signed and ignores
285
+ `:expires`. `valid` is true only while the latest signed record is unexpired. For anything that
286
+ expires you almost always want `valid`; `worldvm check` warns `W_ATTESTED_EXPIRING` and offers
287
+ the fix. Use `attested` for evidence without `:expires` (`HazardPermit`).
288
+ - A requirement satisfied by `(valid E)` can add `:renew-within (days 30)` to open renewal work
289
+ before the record expires.
290
+
291
+ ## 6. Decisions
292
+
293
+ A decision is a person's recorded judgment. It names the requirement it `:applies` to, who may
294
+ make it, and its effect. `(decided name)` reads it in a condition.
295
+
296
+ ```forma world=site file=library/site.forma
297
+ (decision insurance-waiver
298
+ "A site manager may waive insurance with a reason; the waiver lasts six months."
299
+ :of SiteAccess :applies insurance-or-waiver :by (members contractor.managers)
300
+ :effect :approve :reason String :expires (months 6)
301
+ :cites [(site-policy "2: insurance or a manager's time-limited waiver")])
302
+ ```
303
+
304
+ - `:by` is who may decide, usually `(members group-field)`. Anyone else is rejected with
305
+ `:decision-authority` (a scenario can expect that, see [section 9](#9-scenarios-and-properties)).
306
+ - `:effect` is `:approve` (read it with `(decided name)` in `:satisfied-by`), `:waive` (the
307
+ requirement's status becomes `Waived` directly), `:reject`, `:defer`, `:accept` or `:add`.
308
+ - `:reason String` makes a reason mandatory. `:expires (months 6)` ends the decision six months
309
+ after it was made; `:until date` ends it on a date.
310
+ - `:distinct-from [contractor.sponsor]` forbids those people from deciding (separation of
311
+ duties); `:approvals 2` needs two distinct deciders; `:when truth` limits when it may be made.
312
+ - **Inside a decision's `:when`, read facts, requirement and output statuses only.**
313
+ `(met? self.<output>)`, `(satisfied? self.<requirement>)` and fact comparisons work there;
314
+ `(valid E)` and `(attested E)` currently evaluate as false with no diagnostic, so the decision
315
+ is always rejected with `:decision-condition`. Read the requirement that uses them instead.
316
+
317
+ ## 7. Outputs and NotApplicable
318
+
319
+ Every requirement occurrence has one status: `Open`, `Overdue` (open past `:due`), `Satisfied`,
320
+ `Waived`, `NotApplicable` (its `:applies-when` is false) or `Unknown` (a fact it needs is
321
+ missing).
322
+
323
+ An `output` rolls requirements and other outputs up with `(all-of …)`. **`all-of` treats
324
+ `NotApplicable` as satisfied**, so an output is `Satisfied` when every member is `Satisfied`,
325
+ `Waived` or `NotApplicable` and at least one applies; an output whose members are all
326
+ NotApplicable is itself `NotApplicable`. `(satisfied? x)` is true only for `Satisfied` or `Waived`, so
327
+ `(satisfied? requirement)` on a NotApplicable requirement is false. To ask "is everything that
328
+ applies done?", put the requirements in an output and read it with `(met? self.<output>)`.
329
+ `(met? x)` is true for `Satisfied`, `Waived` or `NotApplicable`, so it also counts "nothing
330
+ applies" as met; `(satisfied? self.<output>)` would be false when every member is
331
+ NotApplicable. `worldvm check` warns about both traps with `W_SATISFIED_NOT_APPLICABLE`.
332
+
333
+ ```forma world=site file=library/site.forma
334
+ (component SiteAccess "Clear one contractor for site access and track their badge."
335
+ :key [contractor] :inputs {:contractor (Id site/contractor)}
336
+ (requirement induction
337
+ :cites [(site-policy "1: safety induction within the last twelve months")]
338
+ :applies-when (!= contractor.risk :none)
339
+ :satisfied-by (valid Induction)
340
+ :due (days-after contractor.joined 14))
341
+ (requirement insurance-or-waiver
342
+ :cites [(site-policy "2: insurance or a manager's time-limited waiver")]
343
+ :applies-when (!= contractor.risk :none)
344
+ :satisfied-by (or (valid InsuranceCertificate) (decided insurance-waiver)))
345
+ (requirement hazard-permit
346
+ :cites [(site-policy "3: high-risk work needs a hazard permit")]
347
+ :applies-when (= contractor.risk :high)
348
+ :satisfied-by (attested HazardPermit))
349
+ (requirement badge-activated
350
+ :cites [(site-policy "4: administrators activate badges after clearance")]
351
+ :applies-when (!= contractor.risk :none)
352
+ :satisfied-by (= contractor.badge :active))
353
+ (requirement badge-only-if-cleared
354
+ :cites [(site-policy "4: administrators activate badges after clearance")]
355
+ :applies-when (= contractor.badge :active)
356
+ :satisfied-by (met? self.cleared))
357
+ (invariant no-badge-before-clearance
358
+ :cites [(site-policy "4: administrators activate badges after clearance")]
359
+ :forbids (action-kind :activate :subject contractor)
360
+ :while (not (met? self.cleared)))
361
+ (action induct :advances induction :assignee contractor :via (interaction InductionEntry))
362
+ (action insure :advances insurance-or-waiver :assignee contractor.sponsor
363
+ :via (interaction InsuranceEntry))
364
+ (action permit :advances hazard-permit :assignee contractor.sponsor
365
+ :via (interaction PermitEntry))
366
+ (action activate-badge :advances badge-activated :dispatch :manual
367
+ :needs [(met? self.cleared)]
368
+ :assignee (members contractor.admins) :via (interaction BadgeActivationEntry))
369
+ (output cleared (all-of induction insurance-or-waiver hazard-permit))
370
+ (output access (all-of cleared badge-activated badge-only-if-cleared)))
371
+ ```
372
+
373
+ For a standard-risk contractor `hazard-permit` is NotApplicable, so `cleared` is Satisfied once
374
+ the induction and insurance are. `badge-only-if-cleared` is a _detection_: nothing works on it;
375
+ it turns `Open` when someone activates a badge before clearance or when the induction expires
376
+ (signed on 2026-11-04 in the scenario below, it stops counting on 2027-11-04).
377
+ `worldvm check` reports `W_NO_PRODUCER` for it, which is expected for a detection.
378
+
379
+ ## 8. Actions, interactions and status changes
380
+
381
+ An `action` is work: it `:advances` one requirement, is offered to its `:assignee`, and is done
382
+ `:via` an interaction (or a connector). `:needs [truth …]` gates it: until every need holds, the
383
+ work waits and performing it is rejected (`:not-eligible`). `:dispatch :manual` means the action
384
+ is available on request rather than pushed to the assignee as soon as the requirement opens.
385
+
386
+ Use `:by` with the stable assigned identity in scenario commands, not its display name. Live
387
+ `(do (evidence ...))` records must match an eligible producing action, evidence type and current
388
+ requirement occurrence, and pass the same assignment/signer checks as `perform`. Historical
389
+ `given` records remain available for importing synthetic prior proof without replaying its work.
390
+
391
+ An `interaction` produces one evidence type. Its `layout` decides what the form shows. Its
392
+ `:proposes {role.field evidence-field}` writes signed values back into the subject's facts when
393
+ the evidence is recorded; that is how a world changes a status.
394
+
395
+ Use `:fixes {:examination :remote}` when an interaction supplies a signed value
396
+ instead of asking the signer. The evidence must declare that field with a matching
397
+ scalar type, such as `(Union :in-person :remote)`. Omit fixed fields from the layout,
398
+ including nested groups; they count toward show coverage. A fixed field cannot also
399
+ use `:binds`, `:prefill` or `:proposes`. Conflicting submissions are refused for both
400
+ drafts and signatures. The stored evidence includes the fixed value, so evidence
401
+ rules and explanations can read it. In-person and remote actions can share one
402
+ evidence type through separate interactions fixing different values; gate the remote
403
+ action with `:needs [employee.employer.everify-enrolled]`.
404
+
405
+ **Modelling "activate".** There is no `set-fact` action. To let administrators activate a badge
406
+ only when the contractor is cleared, record the activation as evidence whose interaction
407
+ proposes the new status, behind an action that `:needs` the clearance (see `activate-badge`
408
+ above):
409
+
410
+ ```forma world=site file=library/site.forma
411
+ (evidence BadgeActivation "An administrator's signed badge activation." :of SiteAccess
412
+ {:badge BadgeState}
413
+ (attest :signer assignee :covers :all :method :otp))
414
+ (layout BadgeActivationLayout "Activate the badge."
415
+ (step activate "Activate" (field badge :options {:active "Active"}) (sign)))
416
+ (interaction BadgeActivationEntry "An administrator activates the contractor's badge."
417
+ :actor assignee :produces BadgeActivation :layout BadgeActivationLayout
418
+ :proposes {contractor.badge badge})
419
+
420
+ (layout InductionLayout "Record the induction." (step record "Record" (field course) (sign)))
421
+ (interaction InductionEntry "The contractor completes the safety induction."
422
+ :actor contractor :produces Induction :layout InductionLayout)
423
+ (layout InsuranceLayout "Record the certificate."
424
+ (step record "Record" (field insurer) (field valid-until) (sign)))
425
+ (interaction InsuranceEntry "The sponsor records the insurance certificate."
426
+ :actor contractor.sponsor :produces InsuranceCertificate :layout InsuranceLayout)
427
+ (layout PermitLayout "Record the permit." (step record "Record" (field scope) (sign)))
428
+ (interaction PermitEntry "The sponsor records the hazard permit."
429
+ :actor contractor.sponsor :produces HazardPermit :layout PermitLayout)
430
+ ```
431
+
432
+ `:needs` controls _when_ the activation can happen, not _who_ performs it (see
433
+ [section 3](#3-forms-reference)). When only a group may activate, record the activation as a
434
+ decision instead: `:by` enforces who, and `:when` (over requirement statuses, see
435
+ [section 6](#6-decisions)) enforces when. Early or unauthorised attempts are rejected with
436
+ `:decision-condition` or `:decision-authority`.
437
+
438
+ ```forma world=site file=library/site.forma
439
+ (decision approve-badge
440
+ "A badge administrator approves activation once the contractor is cleared."
441
+ :of SiteAccess :applies badge-activated :by (members contractor.admins)
442
+ :when (met? self.cleared)
443
+ :effect :approve :reason String
444
+ :cites [(site-policy "4: administrators activate badges after clearance")])
445
+ ```
446
+
447
+ **Detect vs prevent.** `badge-only-if-cleared` _detects_ an active badge without clearance after
448
+ the fact. To _prevent_ the write, the component also declares an `invariant`:
449
+ `:forbids (action-kind :activate :subject contractor)` rejects any command of kind `:activate`
450
+ against that contractor while `:while` holds. A write must be submitted as a command with that
451
+ kind to be checked: in a scenario, `(set c :badge :active :kind :activate :subject c :by "Admin")`
452
+ is rejected with the invariant's name (see `badge-write-blocked` below). Writes that bypass the
453
+ command path, or carry another kind, are not checked, and an Unknown `:while` admits the write,
454
+ so keep the detection too. `worldvm check` suggests this pair (`I_DETECT_ONLY`) for a
455
+ detection-only requirement whose `:applies-when` compares a fact to a keyword.
456
+
457
+ ## 9. Scenarios and properties
458
+
459
+ The account package binds entities to the roles and runs the component:
460
+
461
+ ```forma world=site file=example.forma
462
+ (entity Person "A synthetic person." :ns :example.person :display name
463
+ :implements {site/person {:name name}} {:name String})
464
+ (entity Contractor "A synthetic contractor." :ns :example.contractor :display name
465
+ :implements {site/contractor {:name name :sponsor sponsor :managers managers :admins admins
466
+ :risk risk :badge badge :joined joined}}
467
+ {:name String :sponsor (Id Person) :managers Group :admins Group :risk RiskLevel
468
+ :badge BadgeState :joined Date})
469
+ (account example "An isolated synthetic site-access account."
470
+ :requires {example.site-access "1.0"} :package example
471
+ (for-each site/contractor SiteAccess))
472
+ ```
473
+
474
+ A scenario has three kinds of steps, in any order:
475
+
476
+ - `(given …)` creates synthetic data: `(entity Type alias {fields})` and `(actor alias
477
+ [:groups ["Group"]])`. A `Group` field is a string naming the group; an actor is a member when
478
+ its `:groups` lists that name.
479
+ - `(do …)` performs commands. **Commands take effect at the date of the next `(at …)`**, so
480
+ expiry counts from that date.
481
+ - `(perform (Component alias) action :by actor :values {field value})` does an action's work
482
+ through its interaction (rejected if the action is not eligible).
483
+ - `(evidence Type :for (Component alias) :requirement name :by actor :values {…})` records
484
+ evidence directly.
485
+ - `(decide (Component alias) decision :by actor :reason "…")` records a decision.
486
+ - `(set alias :field value :by "who")` changes a fact. Add `:kind :k :subject alias` to submit
487
+ it as a command of kind `:k`, which invariants can reject.
488
+ - `(at "YYYY-MM-DD" (expect selector expected) …)` checks the world on that date:
489
+ - `(status (Component alias) requirement-or-output)` against `:Open`, `:Overdue`,
490
+ `:Satisfied`, `:Waived`, `:NotApplicable` or `:Unknown`;
491
+ - `(work (Component alias) action)` against `{:state :eligible}` (also `:waiting`,
492
+ `:dispatched`, `:held`, `:absent`);
493
+ - `(due (Component alias) requirement)` against a date;
494
+ - `(rejected n)` against the reason the n-th command of the preceding `do` was refused (table
495
+ below). A rejection you do not assert fails the scenario with `E_SCENARIO_RUN`.
496
+
497
+ Two `(at …)` steps may share a date, for example to assert a rejection and then retry.
498
+
499
+ | Rejection | Meaning |
500
+ | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ |
501
+ | `:not-eligible` | The action's `:needs` do not hold. |
502
+ | `:decision-authority` | The actor is not in the decision's `:by`. |
503
+ | `:decision-distinct` | The actor is excluded by `:distinct-from`. |
504
+ | `:decision-reason` | `:reason` is required and missing. |
505
+ | `:decision-condition` | The decision's `:when` does not hold. |
506
+ | `:decision-approvals`, `:decision-duplicate` | An approval count is not met, or the same person approved twice. |
507
+ | `:decision-expiry`, `:decision-until`, `:decision-stale`, `:decision-prior`, `:decision-target`, `:decision-state` | The decision's timing, target or prior state does not allow it. |
508
+ | `:evidence-invalid`, `:signature-required` | The evidence values or signature are missing or invalid. |
509
+ | `:no-occurrence` | The component occurrence does not exist (check the subject and its `:applies-when`). |
510
+ | `:command-date` | The command's date is out of order. |
511
+ | the invariant's name, e.g. `:no-badge-before-clearance` | An invariant forbids this command kind while its `:while` holds. |
512
+
513
+ ```forma world=site file=scenarios/access.forma
514
+ ;; Synthetic data only; illustrative, not compliance advice.
515
+ (scenario standard-clearance "A standard-risk contractor is cleared, then activated."
516
+ :world example
517
+ (given (entity Person sponsor {:name "Sponsor"}) (entity Person admin {:name "Admin"})
518
+ (entity Contractor c {:name "Rivera Electrical" :sponsor sponsor :managers "Managers"
519
+ :admins "Badge admins" :risk :standard :badge :pending
520
+ :joined "2026-11-02"})
521
+ (actor c) (actor sponsor) (actor admin :groups ["Badge admins"]))
522
+ (at "2026-11-02"
523
+ (expect (status (SiteAccess c) induction) :Open)
524
+ (expect (status (SiteAccess c) hazard-permit) :NotApplicable)
525
+ (expect (work (SiteAccess c) activate-badge) {:state :waiting}))
526
+ (do (perform (SiteAccess c) activate-badge :by admin :values {:badge :active}))
527
+ (at "2026-11-03" (expect (rejected 1) :not-eligible))
528
+ (do (perform (SiteAccess c) induct :by c :values {:course "Site safety"})
529
+ (perform (SiteAccess c) insure :by sponsor
530
+ :values {:insurer "Synthetic Mutual" :valid-until "2027-12-31"}))
531
+ (at "2026-11-04"
532
+ (expect (status (SiteAccess c) cleared) :Satisfied)
533
+ (expect (work (SiteAccess c) activate-badge) {:state :eligible}))
534
+ (do (perform (SiteAccess c) activate-badge :by admin :values {:badge :active}))
535
+ (at "2026-11-05"
536
+ (expect (status (SiteAccess c) badge-activated) :Satisfied)
537
+ (expect (status (SiteAccess c) access) :Satisfied))
538
+ (at "2027-11-03" (expect (status (SiteAccess c) access) :Satisfied))
539
+ (at "2027-11-04"
540
+ (expect (status (SiteAccess c) induction) :Overdue)
541
+ (expect (status (SiteAccess c) badge-only-if-cleared) :Open)))
542
+
543
+ (scenario manager-waiver "Only a manager waives insurance, and the waiver lasts six months."
544
+ :world example
545
+ (given (entity Person sponsor {:name "Sponsor"}) (entity Person manager {:name "Manager"})
546
+ (entity Contractor c {:name "Okafor Scaffolds" :sponsor sponsor :managers "Managers"
547
+ :admins "Badge admins" :risk :high :badge :pending
548
+ :joined "2026-11-02"})
549
+ (actor sponsor) (actor manager :groups ["Managers"]))
550
+ (do (decide (SiteAccess c) insurance-waiver :by sponsor :reason "Trust me"))
551
+ (at "2026-11-02"
552
+ (expect (rejected 1) :decision-authority)
553
+ (expect (status (SiteAccess c) hazard-permit) :Open))
554
+ (do (decide (SiteAccess c) insurance-waiver :by manager :reason "Certificate in transit"))
555
+ (at "2026-11-03" (expect (status (SiteAccess c) insurance-or-waiver) :Satisfied))
556
+ (at "2027-05-02" (expect (status (SiteAccess c) insurance-or-waiver) :Satisfied))
557
+ (at "2027-05-03" (expect (status (SiteAccess c) insurance-or-waiver) :Open)))
558
+
559
+ (scenario no-site-work "A contractor who never comes on site has no requirements." :world example
560
+ (given (entity Person sponsor {:name "Sponsor"})
561
+ (entity Contractor c {:name "Remote Design" :sponsor sponsor :managers "Managers"
562
+ :admins "Badge admins" :risk :none :badge :pending
563
+ :joined "2026-11-02"}))
564
+ (at "2026-11-02" (expect (status (SiteAccess c) access) :NotApplicable)))
565
+
566
+ (scenario badge-write-blocked "An activation submitted before clearance is rejected." :world example
567
+ (given (entity Person sponsor {:name "Sponsor"})
568
+ (entity Contractor c {:name "Rivera Electrical" :sponsor sponsor :managers "Managers"
569
+ :admins "Badge admins" :risk :standard :badge :pending
570
+ :joined "2026-11-02"}))
571
+ (do (set c :badge :active :kind :activate :subject c :by "Admin"))
572
+ (at "2026-11-02"
573
+ (expect (rejected 1) :no-badge-before-clearance)
574
+ (expect (status (SiteAccess c) badge-only-if-cleared) :NotApplicable)))
575
+ ```
576
+
577
+ A `property` claims something for every generated entity of a type. `worldvm test` builds
578
+ bounded synthetic worlds from a seed and checks the claim on the `:at` date; false and Unknown
579
+ both fail, and a failure prints a replay scenario. Properties use the property operators from
580
+ [section 4](#4-types-truth-and-comparisons), read facts through the bound name, and select
581
+ statuses with `(status (Component x) name)` and evidence with `(attested (Component x) Type)`.
582
+
583
+ Each `implies` reports how many generated cases made its antecedent true, once per
584
+ case regardless of how many entities matched. Zero produces `W_PROPERTY_VACUOUS`
585
+ in `test` and `coverage`, in text and JSON. Vacuity warns without failing the command;
586
+ false and Unknown results still fail. A passing claim with zero matches has not
587
+ tested its consequent.
588
+
589
+ To reach a claim's preconditions, put an optional scenario-style `(given …)` block
590
+ between `:for-all` and the predicate. It accepts entity, evidence and signal records
591
+ and must declare the quantified alias with its entity type. For example, a property
592
+ quantifying `(p Person)` can seed `(given (entity Person p {:name "Synthetic worker"})
593
+ (evidence Completion :for (Training p) :requirement completed :by p
594
+ :values {:course "Safety 101"}))`. Every case preserves explicit seed facts and
595
+ records while varying unspecified fields; random history cannot replace a seeded
596
+ evidence type or machine on the same occurrence. `given` is trusted history, as in
597
+ scenarios. Use `do` in a scenario to test whether an action is permitted.
598
+ Counterexample shrinking preserves the authored seed facts and records.
599
+
600
+ ```forma world=site file=scenarios/access.forma
601
+ (property active-badge-means-inducted
602
+ "A contractor whose access is satisfied with an active badge has an induction on file."
603
+ :world example :at "2026-11-02" :for-all (c Contractor)
604
+ (implies (and (= c.badge :active) (!= c.risk :none)
605
+ (= (status (SiteAccess c) access) :Satisfied))
606
+ (attested (SiteAccess c) Induction)))
607
+ ```
608
+
609
+ ## 10. Diagnostics catalogue
610
+
611
+ Every diagnostic has a code, a location, `help` and, when the repair is mechanical, a `fix`.
612
+ Errors stop `check`; warnings (`W_…`) and info (`I_…`) are advice. The CLI owns the catalogue:
613
+
614
+ ```sh
615
+ worldvm explain --list
616
+ worldvm explain W_ATTESTED_EXPIRING
617
+ worldvm explain E_NO_HOME
618
+ ```
619
+
620
+ Start with the located help, repair the smallest reported declaration, then rerun `check`.
621
+ Use `valid` for expiring evidence (`W_ATTESTED_EXPIRING`), and `met?` when NotApplicable
622
+ should count as done (`W_SATISFIED_NOT_APPLICABLE`). `W_NO_PRODUCER` asks whether a rule
623
+ needs work to resolve it; a detection-only rule can legitimately have no action. `W_NO_SCENARIO`
624
+ asks for an observed status assertion. A reference alone does not demonstrate the outcome.
625
+
626
+ The catalogue below quotes diagnostic messages verbatim, including internal routing terminology.
627
+ Use `worldvm explain <code>` for details, or `worldvm explain --list` for every code.
628
+
629
+ <!-- catalogue:start -->
630
+
631
+ | Code | Meaning | Usual cause | Fix |
632
+ | ---------------------------------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
633
+ | `E_ADVANCES` | An action's :advances is malformed | :advances must name one requirement or a vector of distinct requirement names. | Use one declared requirement name or a nonempty vector of distinct local names. |
634
+ | `E_ARTIFACT_UNTYPED_RUNTIME_DECLARATION` | Compiler diagnostic (artifact/untyped-runtime-declaration) | The compiler reported E_ARTIFACT_UNTYPED_RUNTIME_DECLARATION, formerly artifact/untyped-runtime-declaration. | Review this declaration and correct the reported syntax, type or reference. |
635
+ | `E_CHECK_THROW` | The compiler threw | An internal compiler failure, not an authoring error. | Reduce the failing source to the smallest example and report it. |
636
+ | `E_CITATION` | A :cites value is malformed | :cites must be a vector of (source "clause") pairs. | Write :cites [(brief-policy "1: clause text")]. |
637
+ | `E_DECISION_EFFECT` | Unsupported decision effect | Decision :effect must be one of the kernel effects. | Choose :approve, :reject, :waive, :defer, :accept or :add. |
638
+ | `E_DECISION_REASON` | Unsupported decision reason type | :reason must be a scalar, a keyword union, or an Option/alias of one. | Use :reason String (or a keyword union); structured records belong in evidence. |
639
+ | `E_DECISION_TARGET` | A decision applies to something its component does not own | :applies names a requirement not declared in the :of component. | Name a requirement declared in the :of component. |
640
+ | `E_ELABORATE_ACTION_DEFINITION` | Compiler diagnostic (elaborate/action-definition) | The compiler reported E_ELABORATE_ACTION_DEFINITION, formerly elaborate/action-definition. | Review this declaration and correct the reported syntax, type or reference. |
641
+ | `E_ELABORATE_CONSTRUCT_FAILED` | Compiler diagnostic (elaborate/construct-failed) | The compiler reported E_ELABORATE_CONSTRUCT_FAILED, formerly elaborate/construct-failed. | Review this declaration and correct the reported syntax, type or reference. |
642
+ | `E_ELABORATE_DUPLICATE_DECLARATION` | Two declarations share a name | Names are global across every .forma file in the world directory. | Rename or delete one declaration. |
643
+ | `E_ELABORATE_EXPANSION_FAILED` | Compiler diagnostic (elaborate/expansion-failed) | The compiler reported E_ELABORATE_EXPANSION_FAILED, formerly elaborate/expansion-failed. | Review this declaration and correct the reported syntax, type or reference. |
644
+ | `E_ELABORATE_FORM_CHECK` | A declaration failed one of its publish checks | The prelude's per-form checks (key closure, unknown fields, and similar) rejected it. | Follow the message; it names the field or child that failed. |
645
+ | `E_ELABORATE_FORM_DEFINITION` | Compiler diagnostic (elaborate/form-definition) | The compiler reported E_ELABORATE_FORM_DEFINITION, formerly elaborate/form-definition. | Review this declaration and correct the reported syntax, type or reference. |
646
+ | `E_ELABORATE_HOLE_TYPE` | An expression has the wrong type for its slot | Most often a Bool where a three-valued Truth is expected: a bare true/false or (if …) in :applies-when/:satisfied-by. Also unbound names and misspelled fields. | Use and, or, not, = and != in every context; collapse Truth to Bool only with (true? x) inside if. |
647
+ | `E_ELABORATE_INVALID_SLOT_VALUE` | An option has a value of the wrong shape | A keyword, vector or map was expected but something else was supplied. | Use the shape named in the message, for example :key [vendor]. |
648
+ | `E_ELABORATE_MALFORMED_FORM` | A form's parts are out of order or malformed | Positional parts (name, docstring, field map) are missing or in the wrong order. | Write (form name "Doc." :option value ... {fields} children...). |
649
+ | `E_ELABORATE_MISSING_IDENTIFIER` | A form is missing its name | The first argument after the form head must be a symbol naming the declaration. | Insert a name: (component VendorReview "Track one vendor." ...). |
650
+ | `E_ELABORATE_MISSING_SLOT` | A required option or part is missing | The form needs a name, docstring, option or field map that was omitted. | Add the missing part named in the message; compare with the minimal world in AUTHORING.md. |
651
+ | `E_ELABORATE_NO_CONSTRUCT_HOOK` | Compiler diagnostic (elaborate/no-construct-hook) | The compiler reported E_ELABORATE_NO_CONSTRUCT_HOOK, formerly elaborate/no-construct-hook. | Review this declaration and correct the reported syntax, type or reference. |
652
+ | `E_ELABORATE_REFERENCE_TYPE` | A reference names the wrong kind of declaration | For example :produces names a role instead of an evidence type, or :of names an entity instead of a component. | Point the option at a declaration of the expected kind (see the message). |
653
+ | `E_ELABORATE_RESULT_TYPE_FAILED` | Compiler diagnostic (elaborate/result-type-failed) | The compiler reported E_ELABORATE_RESULT_TYPE_FAILED, formerly elaborate/result-type-failed. | Review this declaration and correct the reported syntax, type or reference. |
654
+ | `E_ELABORATE_UNKNOWN_FORM` | A top-level form name is not a world declaration | The head of a top-level list is not one of the world forms, or a component/account/evidence child form was written at top level. | Use one of: account, agent, bundle, calendar, collect, component, component-contract, component-import, connector, decision, derive, document, entity, evidence, interaction, layout, library, machine, notice, property, role, scenario, source, type, vault. Child forms such as requirement, action, output and invariant go inside (component ...). |
655
+ | `E_ELABORATE_UNKNOWN_REFERENCE` | A reference names nothing declared | A role, entity, component, evidence, decision or interaction name is misspelled or not declared in any file of the world. | Declare the target or correct the spelling; names are case-sensitive and global to the world directory. |
656
+ | `E_ELABORATE_UNSUPPORTED_FORM` | Compiler diagnostic (elaborate/unsupported-form) | The compiler reported E_ELABORATE_UNSUPPORTED_FORM, formerly elaborate/unsupported-form. | Review this declaration and correct the reported syntax, type or reference. |
657
+ | `E_ELABORATE_VALIDATION_FAILED` | A child form is not valid inside its parent | Usually "Expected child form X-child": a misspelt child inside component, layout, step or evidence. | Help lists the valid children of that parent; correct the child form's head. |
658
+ | `E_EXPIRES_SCOPE` | An evidence :expires reads outside its signed fields | Expiry may read only the evidence's own signed fields, signed-on (the signing date) and pure date logic. | Compute expiry from the signing date, :expires (months-after signed-on 12), or from a signed date field, :expires valid-until. |
659
+ | `E_FIXES_CONFLICT` | A fixed field has another value source | A field is fixed more than once or also uses binds, prefill or proposes. | Give each fixed field exactly one literal value source. |
660
+ | `E_FIXES_LAYOUT` | A layout shows an interaction fixed field | The interaction supplies this value, so the signer must not be prompted for it. | Remove the fixed field from the layout, including nested groups. |
661
+ | `E_FIXES_SHAPE` | Interaction fixed values need a map | :fixes accepts evidence field names and scalar literals. | Use :fixes {:examination :remote}. |
662
+ | `E_FIXES_TYPE` | A fixed value has the wrong evidence field type | The literal does not fit the declared field, including keyword union membership. | Use a scalar literal of the evidence field's declared type. |
663
+ | `E_KEY_NOT_INPUT` | A :key name is not an input | Every :key entry must also appear in :inputs. | Rename the key or the input so they match. |
664
+ | `E_LINK` | An account does not link against its library | The account's :requires names a library/version that is not declared, or an entity does not :implements every role field the library needs. | Match :requires to the (library … :version …) declaration and map every role field in the entity's :implements. |
665
+ | `E_LOWER` | An expression cannot be lowered to the kernel | A name is not in scope, a dotted path names no field, or a call is neither a kernel function nor a derive. | Use kernel functions only: and/or/not for logic, in? for membership; declare a (derive ...) for reusable logic. |
666
+ | `E_MISSING_DOC` | A published declaration has no docstring | Libraries, roles, entities, components, evidence, decisions, scenarios and properties need a nonempty docstring. | Add a docstring right after the name: (component VendorReview "Track one vendor." ...). |
667
+ | `E_NO_HOME` | A component has no entity home | The first :key input must be an entity reference (Id E), directly or through another component. | Put an (Id role) input first in :key, for example :key [vendor]. |
668
+ | `E_NO_SOURCES` | The directory has no .forma files | check/test/coverage compile every visible .forma file under the directory. | Point at the world directory, or scaffold one with worldvm init <dir>. |
669
+ | `E_OUTPUT` | An output expression is not supported | Outputs combine statuses; they are not general expressions. | Write (output name (all-of a b)), (any-of a b) or (status-of a). |
670
+ | `E_PARSE_SYNTAX` | Compiler diagnostic (parse/syntax) | The compiler reported E_PARSE_SYNTAX, formerly parse/syntax. | Review this declaration and correct the reported syntax, type or reference. |
671
+ | `E_PROJECT_IO` | The directory cannot be read | The path does not exist or is not readable. | Pass a readable directory containing .forma source files. |
672
+ | `E_PROPERTY_ASSERT` | A property was false or Unknown for a generated case | The predicate failed; the report includes a shrunk counterexample scenario. | Replay the counterexample source; then correct the rule, or narrow the property with implies/known?. |
673
+ | `E_PROPERTY_DATE` | A property :at is not a real date | Properties never read the system clock; :at must be a fixed date or zoned instant. | Use YYYY-MM-DD, e.g. :at "2026-11-06". |
674
+ | `E_PROPERTY_REF` | A property names an unknown world, binding, field or clause | The :world account, :for-all entity, a field path or a status/evidence name is not declared. | Use an entity in this account package, its declared fields, and a component requirement/output or evidence type. |
675
+ | `E_PROPERTY_SHAPE` | A property expression uses an unsupported form | Properties are closed finite predicates with their own small operator set; runtime vocabulary (valid, decided, days-after …) is not available there. | Use :world, :at and one :for-all (alias Entity), then implies, and, or, not, =, !=, <, <=, >, >=, known?, unknown?, satisfied?, not-applicable?, (status (C alias) name), (attested (C alias) Evidence), work, due, occurrence-count. |
676
+ | `E_PROPERTY_TYPE` | A property operand has the wrong type | Comparison of incompatible values, or a non-boolean under and/or/implies. | Compare like with like (keywords as :high, dates as "YYYY-MM-DD"); logic needs booleans; status predicates need (status …). |
677
+ | `E_READ_OUTSIDE_KEY` | An expression reads a non-key input | Shared/keyed components and decisions may only read key inputs and their reference paths. | Read only key inputs and their reference paths, or include this input in the component key. |
678
+ | `E_READ_SYNTAX` | The file does not parse | Unbalanced parentheses/brackets, an unterminated string or a stray character. | Balance every ( [ { with its closer and close every string; the location points at the first unreadable token. |
679
+ | `E_RENAMED_OPERATOR` | An operator was renamed | The source uses all?, any?, negate or not=. | Use and, or, not and !=. Apply the diagnostic's machine fix; and/or take positional operands or a collection. |
680
+ | `E_ROLE_TYPE_MISMATCH` | A mapped entity field has the wrong type | The entity field bound to a role field has a different type. | Make the types match, using (Id Entity) where the role has (Id role). |
681
+ | `E_SCENARIO_ASSERT` | A scenario expectation did not hold | The observed status, work, rejection or property differed from (expect …). | Inspect the expected/actual values; correct the rule if the example is right, or the example if the rule is right. |
682
+ | `E_SCENARIO_DATE` | A scenario date is invalid or goes backwards | Observation dates must be real dates and nondecreasing. | Use YYYY-MM-DD dates in nondecreasing order. |
683
+ | `E_SCENARIO_NOT_FOUND` | --scenario names no scenario | The name passed to worldvm test --scenario is not declared. | Use one of the names listed in the help. |
684
+ | `E_SCENARIO_REF` | A scenario names something undeclared | An entity alias, account, component, requirement or property is unknown in this scenario. | Use names declared in this world, and declare local aliases in given. |
685
+ | `E_SCENARIO_RUN` | A scenario command could not run | Most often "Unasserted command rejection": a do command was rejected and no (expect (rejected n) …) follows. Also commands that reference state the scenario did not create. | Assert the rejection with (expect (rejected 1) :decision-authority), or fix the command; AUTHORING.md section 9 lists the rejection codes. |
686
+ | `E_SCENARIO_SHAPE` | A scenario block is malformed | Scenarios are (scenario name "Doc." :world account (given …) (do …) (at "date" (expect …)) …). | Use finite given entity/evidence/signal records, do commands, and dated at/expect blocks. |
687
+ | `E_SCENARIO_TYPE` | A scenario value has the wrong type | A literal does not match the declared field or key type. | Use a literal of the declared type (:high for a keyword union, "YYYY-MM-DD" for Date). |
688
+ | `E_SELF_APPROVAL` | The decision authority is excluded from signing | :by names exactly the principal that :distinct-from excludes. | Choose a different principal or a reviewer group. |
689
+ | `E_SOURCE_DATE` | A source :as-of is not a real YYYY-MM-DD date | Dates are zero-padded ISO calendar dates. | Pad the date ("2026-01-02"); a machine fix is offered when the date is otherwise valid. |
690
+ | `E_SOURCE_KIND` | A source has an unsupported :kind | Only a fixed set of source kinds is accepted. | Choose :law, :regulation, :guidance, :framework, :contract or :policy. |
691
+ | `E_SURFACE_INVALID_FORM` | Compiler diagnostic (surface/invalid-form) | The compiler reported E_SURFACE_INVALID_FORM, formerly surface/invalid-form. | Review this declaration and correct the reported syntax, type or reference. |
692
+ | `E_TABLE_NOT_EXHAUSTIVE` | A table does not cover every keyword | A keyword-union selector has a value with no row. | Cover every value of the union, or add :else. |
693
+ | `E_TABLE_SHAPE` | A (table …) is malformed | Tables select on a keyword parameter of a derive. | Use (table keyword-parameter :value result ... :else fallback) inside a derive. |
694
+ | `E_TEST_RUNTIME` | The test engine threw | An internal failure while running a scenario or property. | Reduce the failing scenario/property to its source example and report it. |
695
+ | `E_UNBOUNDED_TIME` | A time expression has no finite bound | Clock reads must compare against a fact-based cutoff so the reconciler can schedule wakeups. | Shift a fact-based date, not the clock: :due (days-after vendor.opened 3). |
696
+ | `E_UNBOUND_ROLE_FIELD` | An entity does not map a role field | The entity's :implements omits a field the role declares. | Map every role field: {role-field entity-field}. |
697
+ | `E_UNKNOWN_FIELD` | A field name is not declared | A rule, layout or binding names a field missing from the evidence or role. | Use a declared evidence or role field name. |
698
+ | `E_UNKNOWN_REQUIREMENT` | A name refers to a requirement that is not declared here | An action's :advances, an output or a decision's :applies names a requirement not declared in the same component. | Name only requirements declared in the same component. |
699
+ | `E_UNKNOWN_SOURCE` | A citation names an undeclared source | :cites refers to a source that has no (source ...) declaration. | Declare the source with (source name ...), then cite its specific clause. |
700
+ | `E_USAGE` | Invalid command line | Unknown subcommand, missing directory or an option the subcommand does not accept. | Run worldvm --help or worldvm <command> --help. |
701
+ | `I_DETECT_ONLY` | This requirement detects a state it could prevent | The requirement has no producer and applies when a fact field has a particular value, so it only flags the state after the write. Nothing blocks the write itself. | Keep the detection, and add an invariant that rejects the labelled write while the review is incomplete: (invariant no-activation-before-review :forbids (action-kind :activate :subject vendor) :while (not (met? self.review-complete))). Scenarios exercise it with (set v :status :active :kind :activate :subject v :by buyer) and (expect (rejected 1) :no-activation-before-review). Only writes submitted as commands with that :kind are checked, and an Unknown :while admits the write. |
702
+ | `I_EXTENDED_FORM` | This form is outside the core language | check --core found an extended declaration or child form. | Use the ten core forms when possible, or keep this form and consult AUTHORING.md for its extended semantics. |
703
+ | `W_ATTESTED_EXPIRING` | attested ignores this evidence's :expires | (attested E) is true once any record was signed, even after it expired. The evidence declares :expires, which suggests validity was intended. | Use (valid E), which is false once the signed expiry passes. A machine fix replaces attested with valid. Keep attested only when historical signing is what matters. |
704
+ | `W_CROSS_HOME_READ` | A read crosses into a home not proven equal | A parent reads a child's output through a reference whose home may differ. | Usually advisory; route the read through a child declared with :bind on the same home if possible. |
705
+ | `W_ERASURE_CONFLICT` | Erasure may conflict with retention | A vault allows on-request erasure while a cited retention obligation still applies. | Resolve the retention obligation before shredding. |
706
+ | `W_NO_PRODUCER` | No action advances this requirement | Nothing can be done to satisfy the requirement from inside the world: no (action … :advances r) and no machine signal. Common and fine for detection requirements that flag a state. | If people should act, add (action do-r :advances r :assignee … :via (interaction …)). If it is a detection, keep it in an output and accept this warning; to block the state instead of flagging it, add an (invariant …) (see AUTHORING.md, Detect vs prevent). |
707
+ | `W_NO_SCENARIO` | No scenario observes this requirement | No scenario expects its status, an output containing it, or work/evidence advancing it. | Add a scenario with (expect (status (Component alias) requirement) :Open) and a step that satisfies it; worldvm coverage shows branches actually taken. |
708
+ | `W_NS_DEFAULTED` | An entity's attribute namespace was defaulted | Without :ns, renaming the entity changes every stored attribute name. | Pin it: :ns :example.vendor. |
709
+ | `W_PROPERTY_VACUOUS` | An implication was never exercised | No generated case made this implies antecedent true; passing does not establish its consequent. | Add a property given block with facts and evidence that exercise the antecedent. Vacuity warns without failing test or coverage. |
710
+ | `W_SATISFIED_NOT_APPLICABLE` | satisfied? is false for NotApplicable | (satisfied? r) is true only for Satisfied or Waived. Reading a requirement with :applies-when inside and or :needs means the conjunction can never hold when r does not apply. Reading an all-of output whose members can all be NotApplicable has the same effect: the output is then NotApplicable too. | Use (met? r), which is true for Satisfied, Waived or NotApplicable, on the requirement or the output. The machine fix replaces satisfied? with met?. |
711
+ | `W_SHOW_COVERAGE_UNPROVEN` | Layout coverage of a required field cannot be proven | A rule's predicate reads non-enum fields, so the checker cannot enumerate cases. | Use keyword enums in rule predicates, or show the field unconditionally. |
712
+ | `W_UNCITED` | A requirement/invariant/retention has no citation | Every obligation should say which source clause it implements. | Add :cites [(source-name "clause")]. |
713
+ | `W_UNHANDLED_STATUS` | A custom child-output expression ignores a status | The expression does not say what happens for NotApplicable or Unknown. | Handle NotApplicable/Unknown explicitly or use all-of/any-of. |
714
+ | `W_UNREACHABLE_REQUIREMENT` | Nothing reads this requirement's status | The requirement is in no output and no expression reads it, so it never affects a result. | Add it to an output, e.g. (output review-complete (all-of questionnaire soc2 dpa)), or remove it. A machine fix is offered when the component has exactly one all-of output. |
715
+
716
+ ### Renamed diagnostic codes
717
+
718
+ | Old code | New code |
719
+ | -------------------------------------- | ---------------------------------------- |
720
+ | `read/syntax` | `E_READ_SYNTAX` |
721
+ | `parse/syntax` | `E_PARSE_SYNTAX` |
722
+ | `surface/invalid-form` | `E_SURFACE_INVALID_FORM` |
723
+ | `artifact/untyped-runtime-declaration` | `E_ARTIFACT_UNTYPED_RUNTIME_DECLARATION` |
724
+ | `elaborate/unknown-form` | `E_ELABORATE_UNKNOWN_FORM` |
725
+ | `elaborate/hole-type` | `E_ELABORATE_HOLE_TYPE` |
726
+ | `elaborate/unknown-reference` | `E_ELABORATE_UNKNOWN_REFERENCE` |
727
+ | `elaborate/reference-type` | `E_ELABORATE_REFERENCE_TYPE` |
728
+ | `elaborate/missing-slot` | `E_ELABORATE_MISSING_SLOT` |
729
+ | `elaborate/invalid-slot-value` | `E_ELABORATE_INVALID_SLOT_VALUE` |
730
+ | `elaborate/malformed-form` | `E_ELABORATE_MALFORMED_FORM` |
731
+ | `elaborate/duplicate-declaration` | `E_ELABORATE_DUPLICATE_DECLARATION` |
732
+ | `elaborate/form-check` | `E_ELABORATE_FORM_CHECK` |
733
+ | `elaborate/missing-identifier` | `E_ELABORATE_MISSING_IDENTIFIER` |
734
+ | `elaborate/validation-failed` | `E_ELABORATE_VALIDATION_FAILED` |
735
+ | `elaborate/action-definition` | `E_ELABORATE_ACTION_DEFINITION` |
736
+ | `elaborate/construct-failed` | `E_ELABORATE_CONSTRUCT_FAILED` |
737
+ | `elaborate/expansion-failed` | `E_ELABORATE_EXPANSION_FAILED` |
738
+ | `elaborate/form-definition` | `E_ELABORATE_FORM_DEFINITION` |
739
+ | `elaborate/no-construct-hook` | `E_ELABORATE_NO_CONSTRUCT_HOOK` |
740
+ | `elaborate/result-type-failed` | `E_ELABORATE_RESULT_TYPE_FAILED` |
741
+ | `elaborate/unsupported-form` | `E_ELABORATE_UNSUPPORTED_FORM` |
742
+
743
+ <!-- catalogue:end -->
744
+
745
+ ```forma broken=W_ATTESTED_EXPIRING
746
+ (library example.expiring "attested ignores expiry." :version "1.0" :subject expiring/item)
747
+ (role expiring/item "An item with an owner." {:owner (Id expiring/item)})
748
+ (evidence Licence "A licence with an end date." :of Expiring :expires valid-until
749
+ {:valid-until Date}
750
+ (attest :signer item.owner :covers :all :method :otp))
751
+ (component Expiring "Warns: attested stays true after expiry." :key [item]
752
+ :inputs {:item (Id expiring/item)}
753
+ (requirement licensed :satisfied-by (attested Licence))
754
+ (output done (all-of licensed)))
755
+ ```
756
+
757
+ ```forma broken=E_ELABORATE_UNKNOWN_FORM
758
+ (requirment stray :satisfied-by true)
759
+ ```
760
+
761
+ ## 11. Units and dates
762
+
763
+ - Dates are strings `"YYYY-MM-DD"`; instants are zoned RFC 3339 strings such as
764
+ `"2026-11-02T09:00:00Z"`, or `(instant "…")` in expressions. `today` is the evaluation date and
765
+ `now` the evaluation instant; the CLI never reads the system clock.
766
+ - Durations: `(days n)`, `(months n)`, `(years n)`, `(hours n)`, `(minutes n)`.
767
+ - Date arithmetic: `(days-after d n)`, `(days-before d n)`, `(months-after d n)`,
768
+ `(years-after d n)`, `(business-days-after d n :calendar cal)`, `(hours-after i n)`,
769
+ `(minutes-after i n)`, `(earliest [d …])`, `(latest [d …])`.
770
+ - Months keep the day of month and clamp to the end of shorter months: January 31 plus one month
771
+ is February 28 (29 in a leap year). Years clamp February 29 to February 28.
772
+ - Expiry relative to signing: `:expires (months-after signed-on 12)` on evidence. Relative to a
773
+ decision: `:expires (months 6)` on the decision. Both are exclusive: the record or decision
774
+ stops counting on that date.
775
+ - `:recur {:every …}`, `:renew-within`, `:reuse :within`, collection `:confirm-after`, escalation
776
+ delays and policy parameter bounds count exact days, years, hours or minutes and reject months.
777
+ Use `(days 30)` or `(years 1)` there.
778
+ - `:due` is a date (or instant); a requirement open after its due date is `Overdue`.
779
+ - A signal-driven case can use `:due (business-days-after (entered-at case :referred) 10 :calendar us-federal)`
780
+ with a declared calendar. `case` must be a machine declared in the current component;
781
+ connector ownership is allowed and no resource declaration is needed. `entered-at` returns
782
+ the UTC Date of the first observation in the latest visit to the state. Consecutive duplicate
783
+ states keep that date; leaving and re-entering resets it. After departure the last entry date
784
+ remains available. Before an observed entry it is Unknown. Managed-resource machines read only
785
+ the current acquisition generation. `resource-generation` and `attested-for` remain resource-only.
786
+
787
+ ## 12. Idioms and anti-patterns
788
+
789
+ - Type the library against roles, never entities. Entities live only in the account package.
790
+ - One component per subject and requirement scope; use `:key` for identity, not a name string.
791
+ - Model flags as keyword unions; avoid comparing a Bool field with `true`.
792
+ - Use `valid` for anything with an expiry; keep `attested` for history.
793
+ - Combine requirements with an output and read it with `(met? self.<output>)`, never by
794
+ conjoining `satisfied?` of requirements that can be NotApplicable.
795
+ - To stop a write rather than flag it, pair the detection with an `invariant` over a labelled
796
+ command (section 8).
797
+ - Cite a clause on every requirement and decision; keep sources synthetic and say so.
798
+ - Every requirement deserves a scenario that shows it Open and one that shows it closed. Run
799
+ `worldvm coverage` to find the ones you missed, then `worldvm coverage --mutate`: each
800
+ surviving mutant (for example `valid` → `attested` still passing) is behaviour no test pins
801
+ down.
802
+ - Decisions are made by people. Agents may draft or recommend, never sign or
803
+ decide.
804
+
805
+ ## 13. Recipes and a complete example
806
+
807
+ **Renewal.** `:renew-within (days N)` on a requirement satisfied by `(valid E)` opens replacement
808
+ work N days before the record expires, while the requirement stays Satisfied:
809
+
810
+ ```forma excerpt
811
+ (requirement questionnaire
812
+ :cites [(vendor-policy "1: completed security questionnaire, renewed every 12 months")]
813
+ :applies-when (!= vendor.tier :none)
814
+ :satisfied-by (valid SecurityQuestionnaire)
815
+ :renew-within (days 30))
816
+ ```
817
+
818
+ **Exception with expiry.** Satisfy a requirement by evidence or by a decision, and give the
819
+ decision `:by`, `:reason` and `:expires`:
820
+
821
+ ```forma excerpt
822
+ (decision approve-exception
823
+ "Only a CISO approves a SOC 2 exception, with a reason; it lasts six months."
824
+ :of VendorReview :applies soc2-or-exception :by (members vendor.cisos)
825
+ :effect :approve :reason String :expires (months 6)
826
+ :cites [(vendor-policy "5: CISO-only exceptions with a reason, expiring after six months")])
827
+ ```
828
+
829
+ These excerpts come from [`docs/authoring/vendor-risk`](docs/authoring/vendor-risk/), a complete
830
+ vendor-review world: 12-month questionnaires from `signed-on`, six-month CISO exceptions, a DPA
831
+ for high-risk vendors, and an activation invariant next to its detection. It passes `check` and
832
+ `test`, and `coverage --mutate` leaves no surviving mutant. `eval/` grades new cold-author worlds
833
+ against the same brief.