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.
- package/AUTHORING.md +833 -0
- package/README.md +154 -2
- package/bin/worldvm.mjs +3 -0
- package/dist/_internal/forma/index.d.ts +1 -0
- package/dist/_internal/forma/index.js +1 -0
- package/dist/_internal/forma/world/authoring-help.d.ts +25 -0
- package/dist/_internal/forma/world/authoring-help.js +130 -0
- package/dist/_internal/forma/world/citations.d.ts +3 -0
- package/dist/_internal/forma/world/citations.js +26 -0
- package/dist/_internal/forma/world/clock-bindings.d.ts +4 -0
- package/dist/_internal/forma/world/clock-bindings.js +45 -0
- package/dist/_internal/forma/world/compile.d.ts +13 -0
- package/dist/_internal/forma/world/compile.js +190 -0
- package/dist/_internal/forma/world/coverage.d.ts +10 -0
- package/dist/_internal/forma/world/coverage.js +242 -0
- package/dist/_internal/forma/world/digest.d.ts +1 -0
- package/dist/_internal/forma/world/digest.js +1 -0
- package/dist/_internal/forma/world/documentation.d.ts +3 -0
- package/dist/_internal/forma/world/documentation.js +38 -0
- package/dist/_internal/forma/world/homes.d.ts +4 -0
- package/dist/_internal/forma/world/homes.js +202 -0
- package/dist/_internal/forma/world/index.d.ts +6 -0
- package/dist/_internal/forma/world/index.js +5 -0
- package/dist/_internal/forma/world/lowering/accounts.d.ts +4 -0
- package/dist/_internal/forma/world/lowering/accounts.js +36 -0
- package/dist/_internal/forma/world/lowering/action-policy.d.ts +5 -0
- package/dist/_internal/forma/world/lowering/action-policy.js +16 -0
- package/dist/_internal/forma/world/lowering/agents.d.ts +6 -0
- package/dist/_internal/forma/world/lowering/agents.js +116 -0
- package/dist/_internal/forma/world/lowering/bundles.d.ts +3 -0
- package/dist/_internal/forma/world/lowering/bundles.js +13 -0
- package/dist/_internal/forma/world/lowering/child-parameters.d.ts +14 -0
- package/dist/_internal/forma/world/lowering/child-parameters.js +36 -0
- package/dist/_internal/forma/world/lowering/collects.d.ts +3 -0
- package/dist/_internal/forma/world/lowering/collects.js +51 -0
- package/dist/_internal/forma/world/lowering/component-operations.d.ts +6 -0
- package/dist/_internal/forma/world/lowering/component-operations.js +26 -0
- package/dist/_internal/forma/world/lowering/components.d.ts +7 -0
- package/dist/_internal/forma/world/lowering/components.js +236 -0
- package/dist/_internal/forma/world/lowering/connectors.d.ts +4 -0
- package/dist/_internal/forma/world/lowering/connectors.js +31 -0
- package/dist/_internal/forma/world/lowering/context.d.ts +80 -0
- package/dist/_internal/forma/world/lowering/context.js +316 -0
- package/dist/_internal/forma/world/lowering/contracts.d.ts +7 -0
- package/dist/_internal/forma/world/lowering/contracts.js +73 -0
- package/dist/_internal/forma/world/lowering/decisions.d.ts +3 -0
- package/dist/_internal/forma/world/lowering/decisions.js +164 -0
- package/dist/_internal/forma/world/lowering/derives.d.ts +3 -0
- package/dist/_internal/forma/world/lowering/derives.js +22 -0
- package/dist/_internal/forma/world/lowering/discretionary.d.ts +7 -0
- package/dist/_internal/forma/world/lowering/discretionary.js +15 -0
- package/dist/_internal/forma/world/lowering/documents.d.ts +3 -0
- package/dist/_internal/forma/world/lowering/documents.js +68 -0
- package/dist/_internal/forma/world/lowering/effective.d.ts +5 -0
- package/dist/_internal/forma/world/lowering/effective.js +26 -0
- package/dist/_internal/forma/world/lowering/entities.d.ts +3 -0
- package/dist/_internal/forma/world/lowering/entities.js +43 -0
- package/dist/_internal/forma/world/lowering/escalations.d.ts +6 -0
- package/dist/_internal/forma/world/lowering/escalations.js +31 -0
- package/dist/_internal/forma/world/lowering/evidence.d.ts +3 -0
- package/dist/_internal/forma/world/lowering/evidence.js +75 -0
- package/dist/_internal/forma/world/lowering/files.d.ts +4 -0
- package/dist/_internal/forma/world/lowering/files.js +56 -0
- package/dist/_internal/forma/world/lowering/holds.d.ts +6 -0
- package/dist/_internal/forma/world/lowering/holds.js +35 -0
- package/dist/_internal/forma/world/lowering/index.d.ts +89 -0
- package/dist/_internal/forma/world/lowering/index.js +115 -0
- package/dist/_internal/forma/world/lowering/interactions.d.ts +7 -0
- package/dist/_internal/forma/world/lowering/interactions.js +190 -0
- package/dist/_internal/forma/world/lowering/library.d.ts +5 -0
- package/dist/_internal/forma/world/lowering/library.js +41 -0
- package/dist/_internal/forma/world/lowering/milestones.d.ts +6 -0
- package/dist/_internal/forma/world/lowering/milestones.js +17 -0
- package/dist/_internal/forma/world/lowering/notices.d.ts +3 -0
- package/dist/_internal/forma/world/lowering/notices.js +33 -0
- package/dist/_internal/forma/world/lowering/param-bounds.d.ts +15 -0
- package/dist/_internal/forma/world/lowering/param-bounds.js +71 -0
- package/dist/_internal/forma/world/lowering/policies.d.ts +6 -0
- package/dist/_internal/forma/world/lowering/policies.js +95 -0
- package/dist/_internal/forma/world/lowering/principals.d.ts +62 -0
- package/dist/_internal/forma/world/lowering/principals.js +32 -0
- package/dist/_internal/forma/world/lowering/recurrences.d.ts +9 -0
- package/dist/_internal/forma/world/lowering/recurrences.js +56 -0
- package/dist/_internal/forma/world/lowering/renewal.d.ts +5 -0
- package/dist/_internal/forma/world/lowering/renewal.js +21 -0
- package/dist/_internal/forma/world/lowering/resources.d.ts +6 -0
- package/dist/_internal/forma/world/lowering/resources.js +19 -0
- package/dist/_internal/forma/world/lowering/reuse.d.ts +5 -0
- package/dist/_internal/forma/world/lowering/reuse.js +75 -0
- package/dist/_internal/forma/world/lowering/sources.d.ts +10 -0
- package/dist/_internal/forma/world/lowering/sources.js +47 -0
- package/dist/_internal/forma/world/lowering/syntax.d.ts +84 -0
- package/dist/_internal/forma/world/lowering/syntax.js +94 -0
- package/dist/_internal/forma/world/lowering/vaults.d.ts +11 -0
- package/dist/_internal/forma/world/lowering/vaults.js +148 -0
- package/dist/_internal/forma/world/prelude.generated.d.ts +1 -0
- package/dist/_internal/forma/world/prelude.generated.js +2 -0
- package/dist/_internal/forma/world/properties.d.ts +9 -0
- package/dist/_internal/forma/world/properties.js +387 -0
- package/dist/_internal/forma/world/scenarios.d.ts +10 -0
- package/dist/_internal/forma/world/scenarios.js +757 -0
- package/dist/_internal/forma/world/sensitivity.d.ts +3 -0
- package/dist/_internal/forma/world/sensitivity.js +118 -0
- package/dist/_internal/forma/world/source-syntax.d.ts +6 -0
- package/dist/_internal/forma/world/source-syntax.js +27 -0
- package/dist/_internal/forma/world/status-handling.d.ts +3 -0
- package/dist/_internal/forma/world/status-handling.js +143 -0
- package/dist/_internal/forma/world/surface.d.ts +30 -0
- package/dist/_internal/forma/world/surface.js +213 -0
- package/dist/_internal/forma/world/table-expressions.d.ts +3 -0
- package/dist/_internal/forma/world/table-expressions.js +41 -0
- package/dist/_internal/forma-tools/index.d.ts +17 -0
- package/dist/_internal/forma-tools/index.js +124 -0
- package/dist/_internal/ir-checks/advances.d.ts +7 -0
- package/dist/_internal/ir-checks/advances.js +6 -0
- package/dist/_internal/ir-checks/agent-reads.d.ts +14 -0
- package/dist/_internal/ir-checks/agent-reads.js +118 -0
- package/dist/_internal/ir-checks/amendments.d.ts +3 -0
- package/dist/_internal/ir-checks/amendments.js +21 -0
- package/dist/_internal/ir-checks/canonical-json.d.ts +3 -0
- package/dist/_internal/ir-checks/canonical-json.js +85 -0
- package/dist/_internal/ir-checks/child-parameters.d.ts +2 -0
- package/dist/_internal/ir-checks/child-parameters.js +43 -0
- package/dist/_internal/ir-checks/clock-bindings.d.ts +3 -0
- package/dist/_internal/ir-checks/clock-bindings.js +43 -0
- package/dist/_internal/ir-checks/collect-types.d.ts +14 -0
- package/dist/_internal/ir-checks/collect-types.js +34 -0
- package/dist/_internal/ir-checks/component-operations.d.ts +4 -0
- package/dist/_internal/ir-checks/component-operations.js +23 -0
- package/dist/_internal/ir-checks/content-digest.d.ts +4 -0
- package/dist/_internal/ir-checks/content-digest.js +78 -0
- package/dist/_internal/ir-checks/contract-validation.d.ts +3 -0
- package/dist/_internal/ir-checks/contract-validation.js +307 -0
- package/dist/_internal/ir-checks/contracts.d.ts +25 -0
- package/dist/_internal/ir-checks/contracts.js +80 -0
- package/dist/_internal/ir-checks/dates.d.ts +2 -0
- package/dist/_internal/ir-checks/dates.js +7 -0
- package/dist/_internal/ir-checks/documents.d.ts +3 -0
- package/dist/_internal/ir-checks/documents.js +45 -0
- package/dist/_internal/ir-checks/evidence.d.ts +20 -0
- package/dist/_internal/ir-checks/evidence.js +56 -0
- package/dist/_internal/ir-checks/files.d.ts +7 -0
- package/dist/_internal/ir-checks/files.js +47 -0
- package/dist/_internal/ir-checks/index.d.ts +59 -0
- package/dist/_internal/ir-checks/index.js +166 -0
- package/dist/_internal/ir-checks/instants.d.ts +7 -0
- package/dist/_internal/ir-checks/instants.js +61 -0
- package/dist/_internal/ir-checks/notices.d.ts +4 -0
- package/dist/_internal/ir-checks/notices.js +58 -0
- package/dist/_internal/ir-checks/policy-bounds.d.ts +5 -0
- package/dist/_internal/ir-checks/policy-bounds.js +28 -0
- package/dist/_internal/ir-checks/principals.d.ts +26 -0
- package/dist/_internal/ir-checks/principals.js +162 -0
- package/dist/_internal/ir-checks/prior-cycle.d.ts +41 -0
- package/dist/_internal/ir-checks/prior-cycle.js +21 -0
- package/dist/_internal/ir-checks/read-classification.d.ts +12 -0
- package/dist/_internal/ir-checks/read-classification.js +67 -0
- package/dist/_internal/ir-checks/read-types.d.ts +2 -0
- package/dist/_internal/ir-checks/read-types.js +40 -0
- package/dist/_internal/ir-checks/resource-proofs.d.ts +4 -0
- package/dist/_internal/ir-checks/resource-proofs.js +98 -0
- package/dist/_internal/ir-checks/resources.d.ts +3 -0
- package/dist/_internal/ir-checks/resources.js +30 -0
- package/dist/_internal/ir-checks/reuse.d.ts +10 -0
- package/dist/_internal/ir-checks/reuse.js +99 -0
- package/dist/_internal/ir-checks/sealing.d.ts +14 -0
- package/dist/_internal/ir-checks/sealing.js +123 -0
- package/dist/_internal/ir-checks/sensitive-flow.d.ts +4 -0
- package/dist/_internal/ir-checks/sensitive-flow.js +240 -0
- package/dist/_internal/ir-checks/sensitivity.d.ts +19 -0
- package/dist/_internal/ir-checks/sensitivity.js +133 -0
- package/dist/_internal/ir-checks/signatures.d.ts +4 -0
- package/dist/_internal/ir-checks/signatures.js +22 -0
- package/dist/_internal/ir-checks/vaults.d.ts +10 -0
- package/dist/_internal/ir-checks/vaults.js +140 -0
- package/dist/_internal/protocol/index.d.ts +1234 -0
- package/dist/_internal/protocol/index.js +215 -0
- package/dist/_internal/reconciler/action-intents.d.ts +17 -0
- package/dist/_internal/reconciler/action-intents.js +161 -0
- package/dist/_internal/reconciler/actions.d.ts +7 -0
- package/dist/_internal/reconciler/actions.js +134 -0
- package/dist/_internal/reconciler/amendments.d.ts +12 -0
- package/dist/_internal/reconciler/amendments.js +52 -0
- package/dist/_internal/reconciler/basis.d.ts +253 -0
- package/dist/_internal/reconciler/basis.js +16 -0
- package/dist/_internal/reconciler/bundles.d.ts +22 -0
- package/dist/_internal/reconciler/bundles.js +110 -0
- package/dist/_internal/reconciler/change-detection.d.ts +5 -0
- package/dist/_internal/reconciler/change-detection.js +82 -0
- package/dist/_internal/reconciler/collection-rules.d.ts +7 -0
- package/dist/_internal/reconciler/collection-rules.js +46 -0
- package/dist/_internal/reconciler/collection-state.d.ts +11 -0
- package/dist/_internal/reconciler/collection-state.js +62 -0
- package/dist/_internal/reconciler/collection-values.d.ts +5 -0
- package/dist/_internal/reconciler/collection-values.js +60 -0
- package/dist/_internal/reconciler/collections.d.ts +35 -0
- package/dist/_internal/reconciler/collections.js +141 -0
- package/dist/_internal/reconciler/commands.d.ts +60 -0
- package/dist/_internal/reconciler/commands.js +468 -0
- package/dist/_internal/reconciler/component-operations.d.ts +48 -0
- package/dist/_internal/reconciler/component-operations.js +256 -0
- package/dist/_internal/reconciler/context.d.ts +38 -0
- package/dist/_internal/reconciler/context.js +44 -0
- package/dist/_internal/reconciler/coverage.d.ts +31 -0
- package/dist/_internal/reconciler/coverage.js +124 -0
- package/dist/_internal/reconciler/dates.d.ts +38 -0
- package/dist/_internal/reconciler/dates.js +121 -0
- package/dist/_internal/reconciler/decide.d.ts +25 -0
- package/dist/_internal/reconciler/decide.js +263 -0
- package/dist/_internal/reconciler/decision-evaluation.d.ts +9 -0
- package/dist/_internal/reconciler/decision-evaluation.js +67 -0
- package/dist/_internal/reconciler/decision-records.d.ts +14 -0
- package/dist/_internal/reconciler/decision-records.js +77 -0
- package/dist/_internal/reconciler/decision-release.d.ts +3 -0
- package/dist/_internal/reconciler/decision-release.js +12 -0
- package/dist/_internal/reconciler/dependencies.d.ts +179 -0
- package/dist/_internal/reconciler/dependencies.js +372 -0
- package/dist/_internal/reconciler/discovery.d.ts +9 -0
- package/dist/_internal/reconciler/discovery.js +65 -0
- package/dist/_internal/reconciler/document-corrections.d.ts +18 -0
- package/dist/_internal/reconciler/document-corrections.js +59 -0
- package/dist/_internal/reconciler/documents.d.ts +26 -0
- package/dist/_internal/reconciler/documents.js +88 -0
- package/dist/_internal/reconciler/effective.d.ts +6 -0
- package/dist/_internal/reconciler/effective.js +17 -0
- package/dist/_internal/reconciler/escalations.d.ts +4 -0
- package/dist/_internal/reconciler/escalations.js +76 -0
- package/dist/_internal/reconciler/evaluation.d.ts +56 -0
- package/dist/_internal/reconciler/evaluation.js +704 -0
- package/dist/_internal/reconciler/evidence-authority.d.ts +6 -0
- package/dist/_internal/reconciler/evidence-authority.js +70 -0
- package/dist/_internal/reconciler/evidence-history.d.ts +5 -0
- package/dist/_internal/reconciler/evidence-history.js +22 -0
- package/dist/_internal/reconciler/evidence-validity.d.ts +17 -0
- package/dist/_internal/reconciler/evidence-validity.js +135 -0
- package/dist/_internal/reconciler/fact-validation.d.ts +5 -0
- package/dist/_internal/reconciler/fact-validation.js +49 -0
- package/dist/_internal/reconciler/files.d.ts +9 -0
- package/dist/_internal/reconciler/files.js +56 -0
- package/dist/_internal/reconciler/graph.d.ts +40 -0
- package/dist/_internal/reconciler/graph.js +298 -0
- package/dist/_internal/reconciler/holds.d.ts +6 -0
- package/dist/_internal/reconciler/holds.js +18 -0
- package/dist/_internal/reconciler/home-definitions.d.ts +11 -0
- package/dist/_internal/reconciler/home-definitions.js +25 -0
- package/dist/_internal/reconciler/homes.d.ts +6 -0
- package/dist/_internal/reconciler/homes.js +32 -0
- package/dist/_internal/reconciler/index.d.ts +42 -0
- package/dist/_internal/reconciler/index.js +58 -0
- package/dist/_internal/reconciler/instants.d.ts +17 -0
- package/dist/_internal/reconciler/instants.js +56 -0
- package/dist/_internal/reconciler/interaction-fields.d.ts +10 -0
- package/dist/_internal/reconciler/interaction-fields.js +30 -0
- package/dist/_internal/reconciler/invariants.d.ts +8 -0
- package/dist/_internal/reconciler/invariants.js +34 -0
- package/dist/_internal/reconciler/journal.d.ts +3 -0
- package/dist/_internal/reconciler/journal.js +4 -0
- package/dist/_internal/reconciler/linking.d.ts +10 -0
- package/dist/_internal/reconciler/linking.js +259 -0
- package/dist/_internal/reconciler/memory.d.ts +32 -0
- package/dist/_internal/reconciler/memory.js +190 -0
- package/dist/_internal/reconciler/milestones.d.ts +7 -0
- package/dist/_internal/reconciler/milestones.js +58 -0
- package/dist/_internal/reconciler/missing.d.ts +18 -0
- package/dist/_internal/reconciler/missing.js +79 -0
- package/dist/_internal/reconciler/model.d.ts +350 -0
- package/dist/_internal/reconciler/model.js +9 -0
- package/dist/_internal/reconciler/notices.d.ts +14 -0
- package/dist/_internal/reconciler/notices.js +80 -0
- package/dist/_internal/reconciler/occurrences.d.ts +3 -0
- package/dist/_internal/reconciler/occurrences.js +30 -0
- package/dist/_internal/reconciler/outputs.d.ts +12 -0
- package/dist/_internal/reconciler/outputs.js +132 -0
- package/dist/_internal/reconciler/parameters.d.ts +4 -0
- package/dist/_internal/reconciler/parameters.js +27 -0
- package/dist/_internal/reconciler/policies.d.ts +22 -0
- package/dist/_internal/reconciler/policies.js +94 -0
- package/dist/_internal/reconciler/policy-edits.d.ts +11 -0
- package/dist/_internal/reconciler/policy-edits.js +42 -0
- package/dist/_internal/reconciler/policy-linking.d.ts +4 -0
- package/dist/_internal/reconciler/policy-linking.js +104 -0
- package/dist/_internal/reconciler/principal-types.d.ts +2 -0
- package/dist/_internal/reconciler/principal-types.js +38 -0
- package/dist/_internal/reconciler/prior-decisions.d.ts +3 -0
- package/dist/_internal/reconciler/prior-decisions.js +34 -0
- package/dist/_internal/reconciler/projections.d.ts +4 -0
- package/dist/_internal/reconciler/projections.js +85 -0
- package/dist/_internal/reconciler/proofs.d.ts +9 -0
- package/dist/_internal/reconciler/proofs.js +24 -0
- package/dist/_internal/reconciler/properties.d.ts +25 -0
- package/dist/_internal/reconciler/properties.js +67 -0
- package/dist/_internal/reconciler/property-eval.d.ts +5 -0
- package/dist/_internal/reconciler/property-eval.js +101 -0
- package/dist/_internal/reconciler/property-generator.d.ts +9 -0
- package/dist/_internal/reconciler/property-generator.js +288 -0
- package/dist/_internal/reconciler/property-shrink.d.ts +14 -0
- package/dist/_internal/reconciler/property-shrink.js +183 -0
- package/dist/_internal/reconciler/provenance.d.ts +8 -0
- package/dist/_internal/reconciler/provenance.js +61 -0
- package/dist/_internal/reconciler/reconcile.d.ts +32 -0
- package/dist/_internal/reconciler/reconcile.js +164 -0
- package/dist/_internal/reconciler/recurrence.d.ts +9 -0
- package/dist/_internal/reconciler/recurrence.js +44 -0
- package/dist/_internal/reconciler/requirements.d.ts +5 -0
- package/dist/_internal/reconciler/requirements.js +331 -0
- package/dist/_internal/reconciler/resource-generation.d.ts +9 -0
- package/dist/_internal/reconciler/resource-generation.js +17 -0
- package/dist/_internal/reconciler/resource-scenarios.d.ts +26 -0
- package/dist/_internal/reconciler/resource-scenarios.js +78 -0
- package/dist/_internal/reconciler/resources.d.ts +24 -0
- package/dist/_internal/reconciler/resources.js +178 -0
- package/dist/_internal/reconciler/result-digest.d.ts +13 -0
- package/dist/_internal/reconciler/result-digest.js +66 -0
- package/dist/_internal/reconciler/reuse.d.ts +16 -0
- package/dist/_internal/reconciler/reuse.js +119 -0
- package/dist/_internal/reconciler/scenarios.d.ts +32 -0
- package/dist/_internal/reconciler/scenarios.js +442 -0
- package/dist/_internal/reconciler/scheduling.d.ts +9 -0
- package/dist/_internal/reconciler/scheduling.js +203 -0
- package/dist/_internal/reconciler/sha256.d.ts +1 -0
- package/dist/_internal/reconciler/sha256.js +1 -0
- package/dist/_internal/reconciler/signatures.d.ts +13 -0
- package/dist/_internal/reconciler/signatures.js +37 -0
- package/dist/_internal/reconciler/temporal.d.ts +10 -0
- package/dist/_internal/reconciler/temporal.js +46 -0
- package/dist/_internal/reconciler/upgrades.d.ts +6 -0
- package/dist/_internal/reconciler/upgrades.js +65 -0
- package/dist/_internal/reconciler/wire.d.ts +2 -0
- package/dist/_internal/reconciler/wire.js +5 -0
- package/dist/_internal/reconciler/work.d.ts +32 -0
- package/dist/_internal/reconciler/work.js +101 -0
- package/dist/_internal/world-ir/schema.generated.d.ts +180 -0
- package/dist/_internal/world-ir/schema.generated.js +1127 -0
- package/dist/_internal/world-ir/types.generated.d.ts +1011 -0
- package/dist/_internal/world-ir/types.generated.js +1 -0
- package/dist/authoring.d.ts +9 -0
- package/dist/authoring.js +10 -0
- package/dist/catalogue.d.ts +20 -0
- package/dist/catalogue.js +531 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +553 -0
- package/dist/codegen.d.ts +6 -0
- package/dist/codegen.js +89 -0
- package/dist/coverage.d.ts +60 -0
- package/dist/coverage.js +128 -0
- package/dist/deploy.d.ts +21 -0
- package/dist/deploy.js +72 -0
- package/dist/diagnostics.d.ts +9 -0
- package/dist/diagnostics.js +37 -0
- package/dist/diff.d.ts +17 -0
- package/dist/diff.js +19 -0
- package/dist/durable-object.d.ts +14 -0
- package/dist/durable-object.js +30 -0
- package/dist/explain.d.ts +113 -0
- package/dist/explain.js +225 -0
- package/dist/fixes.d.ts +4 -0
- package/dist/fixes.js +70 -0
- package/dist/fmt.d.ts +12 -0
- package/dist/fmt.js +39 -0
- package/dist/handle/open.d.ts +18 -0
- package/dist/handle/open.js +28 -0
- package/dist/handle/protocol.d.ts +12 -0
- package/dist/handle/protocol.js +96 -0
- package/dist/handle/store.d.ts +31 -0
- package/dist/handle/store.js +11 -0
- package/dist/handle/types.d.ts +37 -0
- package/dist/handle/types.js +1 -0
- package/dist/handle/world.d.ts +190 -0
- package/dist/handle/world.js +533 -0
- package/dist/http.d.ts +3 -0
- package/dist/http.js +72 -0
- package/dist/impact.d.ts +21 -0
- package/dist/impact.js +57 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.js +43 -0
- package/dist/init.d.ts +13 -0
- package/dist/init.js +99 -0
- package/dist/ir-schema.json +4213 -0
- package/dist/lints.d.ts +8 -0
- package/dist/lints.js +154 -0
- package/dist/lsp.d.ts +14 -0
- package/dist/lsp.js +380 -0
- package/dist/manual/catalog.d.ts +12 -0
- package/dist/manual/catalog.js +23 -0
- package/dist/manual/examples.d.ts +15 -0
- package/dist/manual/examples.js +39 -0
- package/dist/manual/projections.d.ts +77 -0
- package/dist/manual/projections.js +344 -0
- package/dist/manual/prose.d.ts +19 -0
- package/dist/manual/prose.js +215 -0
- package/dist/manual/render.d.ts +76 -0
- package/dist/manual/render.js +250 -0
- package/dist/manual/text.d.ts +7 -0
- package/dist/manual/text.js +15 -0
- package/dist/mcp.d.ts +32 -0
- package/dist/mcp.js +269 -0
- package/dist/mutate.d.ts +36 -0
- package/dist/mutate.js +123 -0
- package/dist/project.d.ts +26 -0
- package/dist/project.js +80 -0
- package/dist/refine.d.ts +18 -0
- package/dist/refine.js +197 -0
- package/dist/release/diff.d.ts +45 -0
- package/dist/release/diff.js +103 -0
- package/dist/release/impact.d.ts +83 -0
- package/dist/release/impact.js +214 -0
- package/dist/release/nodes.d.ts +20 -0
- package/dist/release/nodes.js +118 -0
- package/dist/render.d.ts +19 -0
- package/dist/render.js +43 -0
- package/dist/serve.d.ts +18 -0
- package/dist/serve.js +140 -0
- package/dist/snapshot.d.ts +19 -0
- package/dist/snapshot.js +45 -0
- package/dist/sqlite.d.ts +16 -0
- package/dist/sqlite.js +151 -0
- package/dist/test.d.ts +54 -0
- package/dist/test.js +131 -0
- package/dist/world.d.ts +7 -0
- package/dist/world.js +5 -0
- package/docs/authoring/vendor-risk/example.forma +11 -0
- package/docs/authoring/vendor-risk/library/vendor.forma +76 -0
- package/docs/authoring/vendor-risk/scenarios/reviews.forma +107 -0
- package/docs/protocol.md +195 -0
- package/docs/reference.md +258 -0
- package/package.json +81 -3
|
@@ -0,0 +1,757 @@
|
|
|
1
|
+
import { sourceSyntax } from "./source-syntax.js";
|
|
2
|
+
import { sensitivePayload } from "../../ir-checks/index.js";
|
|
3
|
+
import { fileDigest, fileMediaType, isLocalDate, normalizeInstant, timePointKey, } from "../../ir-checks/index.js";
|
|
4
|
+
import { priorCycleOperationName } from "../../ir-checks/index.js";
|
|
5
|
+
import {} from "@forma-language/forma/reader";
|
|
6
|
+
const name = (e) => (e?._tag === "Sym" ? e.name : undefined);
|
|
7
|
+
const list = (e) => e?._tag === "List" || e?._tag === "Vector" ? e.items : [];
|
|
8
|
+
const head = (e) => (e._tag === "List" ? name(e.items[0]) : undefined);
|
|
9
|
+
const option = (e, key) => {
|
|
10
|
+
const xs = list(e), i = xs.findIndex((x) => name(x) === `:${key}`);
|
|
11
|
+
return i < 0 ? undefined : xs[i + 1];
|
|
12
|
+
};
|
|
13
|
+
class InvalidScenario extends Error {
|
|
14
|
+
code;
|
|
15
|
+
at;
|
|
16
|
+
help;
|
|
17
|
+
constructor(code, message, at, help) {
|
|
18
|
+
super(message);
|
|
19
|
+
this.code = code;
|
|
20
|
+
this.at = at;
|
|
21
|
+
this.help = help;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/** Finite authored data only; resolving aliases never discovers runtime entities. */
|
|
25
|
+
export const compileScenarios = (ir, files, forms) => {
|
|
26
|
+
const scenarios = [], diagnostics = [];
|
|
27
|
+
const aliases = new Map(ir.types.map((t) => [t.name, t.type]));
|
|
28
|
+
const unalias = (t, seen = new Set()) => {
|
|
29
|
+
if (typeof t !== "string" || !aliases.has(t) || seen.has(t))
|
|
30
|
+
return t;
|
|
31
|
+
seen.add(t);
|
|
32
|
+
return unalias(aliases.get(t), seen);
|
|
33
|
+
};
|
|
34
|
+
for (const file of files)
|
|
35
|
+
for (const form of forms ?? sourceSyntax(file).forms) {
|
|
36
|
+
if (head(form) !== "scenario")
|
|
37
|
+
continue;
|
|
38
|
+
const at = (e = form) => ({
|
|
39
|
+
src: file.id,
|
|
40
|
+
from: e.loc.start,
|
|
41
|
+
to: e.loc.end,
|
|
42
|
+
line: e.loc.line,
|
|
43
|
+
col: e.loc.col,
|
|
44
|
+
});
|
|
45
|
+
const fail = (code, message, e, help) => {
|
|
46
|
+
throw new InvalidScenario(code, message, at(e), help);
|
|
47
|
+
};
|
|
48
|
+
const shape = (message, e) => fail("E_SCENARIO_SHAPE", message, e, "Use finite given entity/evidence/signal records, do commands, and dated at/expect blocks.");
|
|
49
|
+
const reference = (message, e) => fail("E_SCENARIO_REF", message, e, "Use an entity, account, component, property or clause declared in this world, and declare local aliases in given.");
|
|
50
|
+
const mismatch = (e) => fail("E_SCENARIO_TYPE", "Scenario value does not match its declared type.", e, "Use a literal of the declared field/key type, a compatible given entity alias, or a declared component reference.");
|
|
51
|
+
const readDate = (e) => {
|
|
52
|
+
if (e?._tag !== "Str" || (!isLocalDate(e.value) && !normalizeInstant(e.value)))
|
|
53
|
+
return fail("E_SCENARIO_DATE", "Expected a real local date or explicitly zoned scenario instant.", e, "Use YYYY-MM-DD or an explicitly zoned RFC3339 instant; observation times must be nondecreasing.");
|
|
54
|
+
return isLocalDate(e.value) ? e.value : normalizeInstant(e.value);
|
|
55
|
+
};
|
|
56
|
+
try {
|
|
57
|
+
const world = option(form, "world"), account = ir.accounts.find((a) => a.name === name(world));
|
|
58
|
+
if (!account)
|
|
59
|
+
reference("Unknown scenario world.", world);
|
|
60
|
+
const authored = list(form), start = authored[2]?._tag === "Str" ? 3 : 2;
|
|
61
|
+
const blocks = authored.slice(start + 2);
|
|
62
|
+
for (const block of blocks)
|
|
63
|
+
if (block._tag !== "List")
|
|
64
|
+
shape("Scenario blocks must be lists.", block);
|
|
65
|
+
const givenBlocks = blocks.filter((e) => head(e) === "given");
|
|
66
|
+
if (givenBlocks.length > 1)
|
|
67
|
+
shape("A scenario has at most one given block.", givenBlocks[1]);
|
|
68
|
+
const declarations = givenBlocks.flatMap((e) => list(e).slice(1));
|
|
69
|
+
const actorAliases = new Set(declarations
|
|
70
|
+
.filter((e) => head(e) === "actor")
|
|
71
|
+
.map((e) => name(list(e)[1]))
|
|
72
|
+
.filter((n) => !!n));
|
|
73
|
+
const local = new Map();
|
|
74
|
+
for (const e of declarations.filter((e) => head(e) === "entity")) {
|
|
75
|
+
const xs = list(e), type = ir.entities.find((t) => t.name === name(xs[1])), alias = name(xs[2]);
|
|
76
|
+
if (head(e) !== "entity" || xs.length !== 4 || !alias)
|
|
77
|
+
shape("Given records are (entity Type alias {fields}).", e);
|
|
78
|
+
if (!type || type.ns.split(".")[0] !== account.package.name)
|
|
79
|
+
reference("Unknown entity type in this world.", xs[1]);
|
|
80
|
+
if (local.has(alias))
|
|
81
|
+
shape("Given aliases must be unique.", xs[2]);
|
|
82
|
+
local.set(alias, type);
|
|
83
|
+
}
|
|
84
|
+
const compatible = (entity, target) => entity.name === target || entity.implements.some((b) => b.role === target);
|
|
85
|
+
const instance = (e) => {
|
|
86
|
+
const xs = list(e), component = ir.components.find((c) => c.name === name(xs[0]));
|
|
87
|
+
if (e?._tag !== "List")
|
|
88
|
+
return shape("Use (Component key...) for an occurrence.", e);
|
|
89
|
+
if (!component)
|
|
90
|
+
return reference("Unknown scenario component.", xs[0]);
|
|
91
|
+
const end = component.key.length + 1;
|
|
92
|
+
let cycle;
|
|
93
|
+
if (xs.length !== end) {
|
|
94
|
+
if (xs.length !== end + 2 || name(xs[end]) !== ":cycle")
|
|
95
|
+
return shape("Occurrence keys must match the component's key arity; optionally add :cycle N.", e);
|
|
96
|
+
const n = xs[end + 1];
|
|
97
|
+
if (n?._tag !== "Num" || !Number.isSafeInteger(Number(n.value)) || Number(n.value) < 1)
|
|
98
|
+
return mismatch(n);
|
|
99
|
+
cycle = Number(n.value);
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
k: "instance",
|
|
103
|
+
component: component.name,
|
|
104
|
+
...(cycle === undefined ? {} : { cycle }),
|
|
105
|
+
key: component.key.map((key, i) => {
|
|
106
|
+
const result = value(xs[i + 1], component.inputs.find((f) => f.name === key).type);
|
|
107
|
+
if (result.k === "literal" && result.value === null)
|
|
108
|
+
return mismatch(xs[i + 1]);
|
|
109
|
+
return result;
|
|
110
|
+
}),
|
|
111
|
+
at: at(e),
|
|
112
|
+
};
|
|
113
|
+
};
|
|
114
|
+
const value = (e, original) => {
|
|
115
|
+
const t = unalias(original);
|
|
116
|
+
if (name(e) === "nil")
|
|
117
|
+
return { k: "literal", value: null, at: at(e) };
|
|
118
|
+
if (Array.isArray(t)) {
|
|
119
|
+
const payload = sensitivePayload(t);
|
|
120
|
+
if (payload)
|
|
121
|
+
return value(e, payload);
|
|
122
|
+
if (t[0] === "Option" || t[0] === "Brand")
|
|
123
|
+
return value(e, t[1]);
|
|
124
|
+
if (t[0] === "Id" && typeof t[1] === "string") {
|
|
125
|
+
if (ir.components.some((c) => c.name === t[1])) {
|
|
126
|
+
const ref = instance(e);
|
|
127
|
+
if (ref.component !== t[1])
|
|
128
|
+
return mismatch(e);
|
|
129
|
+
return ref;
|
|
130
|
+
}
|
|
131
|
+
const alias = name(e), entity = local.get(alias ?? "");
|
|
132
|
+
if (!entity)
|
|
133
|
+
return reference("Unknown given entity alias.", e);
|
|
134
|
+
if (!compatible(entity, t[1]))
|
|
135
|
+
return mismatch(e);
|
|
136
|
+
return { k: "entity", name: alias, at: at(e) };
|
|
137
|
+
}
|
|
138
|
+
if (t[0] === "Union" && name(e)?.startsWith(":")) {
|
|
139
|
+
if (!t.slice(1).includes(name(e)))
|
|
140
|
+
return mismatch(e);
|
|
141
|
+
return { k: "literal", value: name(e).slice(1), at: at(e) };
|
|
142
|
+
}
|
|
143
|
+
return mismatch(e);
|
|
144
|
+
}
|
|
145
|
+
let v;
|
|
146
|
+
if (e._tag === "Str")
|
|
147
|
+
v = e.value;
|
|
148
|
+
else if (e._tag === "Bool")
|
|
149
|
+
v = e.value;
|
|
150
|
+
else if (e._tag === "Num")
|
|
151
|
+
v = Number(e.value);
|
|
152
|
+
else if (name(e)?.startsWith(":"))
|
|
153
|
+
v = name(e).slice(1);
|
|
154
|
+
else
|
|
155
|
+
return mismatch(e);
|
|
156
|
+
if ((t === "String" || t === "Group") && e._tag !== "Str")
|
|
157
|
+
return mismatch(e);
|
|
158
|
+
if (t === "Keyword" && !name(e)?.startsWith(":"))
|
|
159
|
+
return mismatch(e);
|
|
160
|
+
if (t === "Bool" && typeof v !== "boolean")
|
|
161
|
+
return mismatch(e);
|
|
162
|
+
if ((t === "Int" || t === "Float") &&
|
|
163
|
+
(typeof v !== "number" ||
|
|
164
|
+
!Number.isFinite(v) ||
|
|
165
|
+
(t === "Int" && !Number.isSafeInteger(v))))
|
|
166
|
+
return mismatch(e);
|
|
167
|
+
if (t === "File" && (e._tag !== "Str" || !fileDigest(e.value)))
|
|
168
|
+
return mismatch(e);
|
|
169
|
+
if (t === "Date" && (e._tag !== "Str" || !isLocalDate(e.value)))
|
|
170
|
+
return mismatch(e);
|
|
171
|
+
if (t === "Instant") {
|
|
172
|
+
if (e._tag !== "Str" || !normalizeInstant(e.value))
|
|
173
|
+
return mismatch(e);
|
|
174
|
+
v = normalizeInstant(e.value);
|
|
175
|
+
}
|
|
176
|
+
if (![
|
|
177
|
+
"String",
|
|
178
|
+
"Group",
|
|
179
|
+
"Keyword",
|
|
180
|
+
"Bool",
|
|
181
|
+
"Int",
|
|
182
|
+
"Float",
|
|
183
|
+
"Date",
|
|
184
|
+
"Instant",
|
|
185
|
+
"File",
|
|
186
|
+
].includes(String(t)))
|
|
187
|
+
return mismatch(e);
|
|
188
|
+
return { k: "literal", value: v, at: at(e) };
|
|
189
|
+
};
|
|
190
|
+
const given = declarations
|
|
191
|
+
.filter((e) => head(e) === "entity")
|
|
192
|
+
.map((e) => {
|
|
193
|
+
const xs = list(e), alias = name(xs[2]), entity = local.get(alias), fields = xs[3];
|
|
194
|
+
if (fields?._tag !== "Map")
|
|
195
|
+
return shape("Given fields must be a keyword-keyed record.", fields);
|
|
196
|
+
const seen = new Set();
|
|
197
|
+
return {
|
|
198
|
+
name: alias,
|
|
199
|
+
entity: entity.name,
|
|
200
|
+
fields: fields.pairs.map(([key, v]) => {
|
|
201
|
+
const field = entity.fields.find((f) => `:${f.name}` === name(key));
|
|
202
|
+
if (!field)
|
|
203
|
+
return reference("Unknown scenario entity field.", key);
|
|
204
|
+
if (seen.has(field.name))
|
|
205
|
+
return shape("Given fields must be unique.", key);
|
|
206
|
+
seen.add(field.name);
|
|
207
|
+
const result = value(v, field.type);
|
|
208
|
+
if (result.k === "instance")
|
|
209
|
+
return mismatch(v);
|
|
210
|
+
return { name: field.name, value: result, at: at(key) };
|
|
211
|
+
}),
|
|
212
|
+
at: at(e),
|
|
213
|
+
};
|
|
214
|
+
});
|
|
215
|
+
const options = (e, start, allowed) => {
|
|
216
|
+
const xs = list(e), out = new Map();
|
|
217
|
+
for (let i = start; i < xs.length; i += 2) {
|
|
218
|
+
const key = name(xs[i]);
|
|
219
|
+
if (!key?.startsWith(":") ||
|
|
220
|
+
!allowed.includes(key.slice(1)) ||
|
|
221
|
+
out.has(key.slice(1)) ||
|
|
222
|
+
!xs[i + 1])
|
|
223
|
+
return shape("Use each supported command option once with a value.", xs[i]);
|
|
224
|
+
out.set(key.slice(1), xs[i + 1]);
|
|
225
|
+
}
|
|
226
|
+
return out;
|
|
227
|
+
};
|
|
228
|
+
const actor = (e) => {
|
|
229
|
+
if (!e)
|
|
230
|
+
return { k: "literal", value: "scenario", at: at() };
|
|
231
|
+
if (e._tag === "Str")
|
|
232
|
+
return { k: "literal", value: e.value, at: at(e) };
|
|
233
|
+
if (!local.has(name(e) ?? "") && !actorAliases.has(name(e) ?? ""))
|
|
234
|
+
return reference("Unknown scenario actor alias.", e);
|
|
235
|
+
return { k: "entity", name: name(e), at: at(e) };
|
|
236
|
+
};
|
|
237
|
+
const fields = (e, declared) => {
|
|
238
|
+
if (!e)
|
|
239
|
+
return [];
|
|
240
|
+
if (e._tag !== "Map")
|
|
241
|
+
return shape("Use a keyword-keyed values record.", e);
|
|
242
|
+
const seen = new Set();
|
|
243
|
+
return e.pairs.map(([key, v]) => {
|
|
244
|
+
const field = declared.find((f) => `:${f.name}` === name(key));
|
|
245
|
+
if (!field)
|
|
246
|
+
return reference("Unknown evidence field.", key);
|
|
247
|
+
if (seen.has(field.name))
|
|
248
|
+
return shape("Evidence fields must be unique.", key);
|
|
249
|
+
seen.add(field.name);
|
|
250
|
+
const result = value(v, field.type);
|
|
251
|
+
if (result.k === "instance")
|
|
252
|
+
return mismatch(v);
|
|
253
|
+
return { name: field.name, value: result, at: at(key) };
|
|
254
|
+
});
|
|
255
|
+
};
|
|
256
|
+
const actors = [];
|
|
257
|
+
for (const declaration of declarations.filter((e) => head(e) === "actor")) {
|
|
258
|
+
const xs = list(declaration), alias = name(xs[1]), opts = options(declaration, 2, ["kind", "groups"]);
|
|
259
|
+
if (!alias || alias.startsWith(":"))
|
|
260
|
+
shape("Use (actor alias :kind :human|:agent :groups [group-id...]).", declaration);
|
|
261
|
+
if (actors.some((a) => a.name === alias))
|
|
262
|
+
shape("Actor profiles must be unique.", xs[1]);
|
|
263
|
+
const kind = opts.has("kind") ? name(opts.get("kind")) : ":human", groups = opts.get("groups");
|
|
264
|
+
if (kind !== ":human" && kind !== ":agent")
|
|
265
|
+
mismatch(opts.get("kind"));
|
|
266
|
+
if (groups && groups._tag !== "Vector")
|
|
267
|
+
mismatch(groups);
|
|
268
|
+
const names = list(groups).map((g) => {
|
|
269
|
+
if (g._tag !== "Str" || !g.value.trim())
|
|
270
|
+
return mismatch(g);
|
|
271
|
+
return g.value;
|
|
272
|
+
});
|
|
273
|
+
actors.push({
|
|
274
|
+
name: alias,
|
|
275
|
+
kind: kind === ":agent" ? "agent" : "human",
|
|
276
|
+
groups: [...new Set(names)],
|
|
277
|
+
at: at(declaration),
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
const record = (e) => {
|
|
281
|
+
const xs = list(e), kind = head(e);
|
|
282
|
+
if (kind !== "evidence" && kind !== "signal")
|
|
283
|
+
return shape("Use an evidence or signal record.", e);
|
|
284
|
+
const opts = options(e, kind === "evidence" ? 2 : 3, kind === "evidence"
|
|
285
|
+
? ["for", "requirement", "requirement-cycle", "by", "status", "on", "values"]
|
|
286
|
+
: ["state", "by", "on"]);
|
|
287
|
+
const target = instance(kind === "evidence" ? opts.get("for") : xs[1]), component = ir.components.find((c) => c.name === target.component), common = {
|
|
288
|
+
target,
|
|
289
|
+
by: actor(opts.get("by")),
|
|
290
|
+
...(opts.has("on") ? { date: readDate(opts.get("on")) } : {}),
|
|
291
|
+
at: at(e),
|
|
292
|
+
};
|
|
293
|
+
if (kind === "signal") {
|
|
294
|
+
const machine = component.machines.find((m) => m.name === name(xs[2]));
|
|
295
|
+
if (!machine)
|
|
296
|
+
return reference("Unknown component machine.", xs[2]);
|
|
297
|
+
const protocol = ir.machines.find((m) => m.name === machine.protocol), state = name(opts.get("state"));
|
|
298
|
+
if (!protocol ||
|
|
299
|
+
!state?.startsWith(":") ||
|
|
300
|
+
!protocol.states.some((s) => s.name === state.slice(1)))
|
|
301
|
+
return reference("Unknown machine state.", opts.get("state"));
|
|
302
|
+
return { ...common, kind, machine: machine.name, state: state.slice(1) };
|
|
303
|
+
}
|
|
304
|
+
const evidence = ir.evidence.find((v) => v.name === name(xs[1]));
|
|
305
|
+
if (!evidence || evidence.of !== component.name)
|
|
306
|
+
return reference("Unknown evidence type for this component.", xs[1]);
|
|
307
|
+
const requirement = component.requirements.find((r) => r.name === name(opts.get("requirement")));
|
|
308
|
+
if (!requirement)
|
|
309
|
+
return reference("Unknown evidence requirement.", opts.get("requirement"));
|
|
310
|
+
const cycle = opts.get("requirement-cycle");
|
|
311
|
+
if (cycle &&
|
|
312
|
+
(cycle._tag !== "Num" ||
|
|
313
|
+
!Number.isSafeInteger(Number(cycle.value)) ||
|
|
314
|
+
Number(cycle.value) < 1 ||
|
|
315
|
+
requirement.cycle?.k !== "call" ||
|
|
316
|
+
requirement.cycle.fn !== "resource-generation"))
|
|
317
|
+
return reference("Use a positive integer :requirement-cycle only for an explicitly resource-generation-cycled requirement.", cycle);
|
|
318
|
+
const status = opts.has("status") ? name(opts.get("status")) : ":attested";
|
|
319
|
+
if (!status || ![":submitted", ":attested", ":superseded"].includes(status))
|
|
320
|
+
return mismatch(opts.get("status"));
|
|
321
|
+
return {
|
|
322
|
+
...common,
|
|
323
|
+
kind,
|
|
324
|
+
evidence: evidence.name,
|
|
325
|
+
requirement: requirement.name,
|
|
326
|
+
...(cycle
|
|
327
|
+
? { requirementCycle: Number(cycle.value) }
|
|
328
|
+
: {}),
|
|
329
|
+
status: status.slice(1),
|
|
330
|
+
values: fields(opts.get("values"), evidence.fields),
|
|
331
|
+
};
|
|
332
|
+
};
|
|
333
|
+
const command = (e) => {
|
|
334
|
+
const xs = list(e), kind = head(e);
|
|
335
|
+
if (kind === "evidence" || kind === "signal")
|
|
336
|
+
return record(e);
|
|
337
|
+
if (kind === "resource") {
|
|
338
|
+
const target = instance(xs[1]), component = ir.components.find((c) => c.name === target.component), resource = component.resources?.find((r) => r.name === name(xs[2]));
|
|
339
|
+
if (!resource)
|
|
340
|
+
return reference("Unknown component resource.", xs[2]);
|
|
341
|
+
const opts = options(e, 3, ["phase", "handle", "state", "by"]), phase = name(opts.get("phase")), handle = opts.get("handle"), state = name(opts.get("state"));
|
|
342
|
+
if (phase !== ":acquire" && phase !== ":release")
|
|
343
|
+
return mismatch(opts.get("phase"));
|
|
344
|
+
if (handle?._tag !== "Str" || !handle.value.trim())
|
|
345
|
+
return mismatch(handle);
|
|
346
|
+
if (opts.has("state")) {
|
|
347
|
+
const machine = component.machines.find((m) => m.name === resource.name), protocol = ir.machines.find((m) => m.name === machine.protocol);
|
|
348
|
+
if (phase === ":release" ||
|
|
349
|
+
!state?.startsWith(":") ||
|
|
350
|
+
!protocol.states.some((s) => s.name === state.slice(1)))
|
|
351
|
+
return reference("Unknown resource observation state.", opts.get("state"));
|
|
352
|
+
}
|
|
353
|
+
return {
|
|
354
|
+
kind,
|
|
355
|
+
target,
|
|
356
|
+
name: resource.name,
|
|
357
|
+
phase: phase.slice(1),
|
|
358
|
+
handle: handle.value,
|
|
359
|
+
...(state ? { state: state.slice(1) } : {}),
|
|
360
|
+
by: actor(opts.get("by")),
|
|
361
|
+
at: at(e),
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
if (kind === "decide") {
|
|
365
|
+
const opts = options(e, 3, ["id", "by", "reason", "revoke"]), target = instance(xs[1]);
|
|
366
|
+
const definition = ir.decisions?.find((d) => d.name === name(xs[2]) && d.of === target.component);
|
|
367
|
+
if (!definition)
|
|
368
|
+
return reference("Unknown decision on this component.", xs[2]);
|
|
369
|
+
const text = (key) => {
|
|
370
|
+
const v = opts.get(key);
|
|
371
|
+
if (!v)
|
|
372
|
+
return undefined;
|
|
373
|
+
if (v._tag !== "Str" || !v.value.trim())
|
|
374
|
+
return mismatch(v);
|
|
375
|
+
return v.value;
|
|
376
|
+
};
|
|
377
|
+
const id = text("id"), revoke = text("revoke"), rawReason = opts.get("reason"), reason = rawReason ? value(rawReason, definition.reason) : undefined;
|
|
378
|
+
if (reason && reason.k !== "literal")
|
|
379
|
+
return mismatch(rawReason);
|
|
380
|
+
return {
|
|
381
|
+
kind,
|
|
382
|
+
target,
|
|
383
|
+
decision: definition.name,
|
|
384
|
+
by: actor(opts.get("by")),
|
|
385
|
+
...(id ? { id } : {}),
|
|
386
|
+
...(revoke ? { revoke } : {}),
|
|
387
|
+
...(reason?.k === "literal" ? { reason: reason.value } : {}),
|
|
388
|
+
at: at(e),
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
if (kind === "set") {
|
|
392
|
+
const opts = options(e, 4, ["by", "kind", "subject"]), entity = local.get(name(xs[1]) ?? "");
|
|
393
|
+
if (!entity)
|
|
394
|
+
return reference("Unknown given entity alias.", xs[1]);
|
|
395
|
+
const field = entity.fields.find((f) => `:${f.name}` === name(xs[2]));
|
|
396
|
+
if (!field)
|
|
397
|
+
return reference("Unknown entity field.", xs[2]);
|
|
398
|
+
if (!xs[3])
|
|
399
|
+
return shape("Set needs a field value.", e);
|
|
400
|
+
const result = value(xs[3], field.type);
|
|
401
|
+
if (result.k === "instance")
|
|
402
|
+
return mismatch(xs[3]);
|
|
403
|
+
const commandKind = opts.get("kind"), subject = opts.get("subject");
|
|
404
|
+
if (commandKind && !name(commandKind)?.startsWith(":"))
|
|
405
|
+
return mismatch(commandKind);
|
|
406
|
+
if (subject && !local.has(name(subject) ?? ""))
|
|
407
|
+
return reference("Unknown command subject alias.", subject);
|
|
408
|
+
return {
|
|
409
|
+
kind,
|
|
410
|
+
...(commandKind ? { commandKind: name(commandKind).slice(1) } : {}),
|
|
411
|
+
...(subject ? { subject: name(subject) } : {}),
|
|
412
|
+
entity: name(xs[1]),
|
|
413
|
+
field: field.name,
|
|
414
|
+
value: result,
|
|
415
|
+
by: actor(opts.get("by")),
|
|
416
|
+
at: at(e),
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
if (kind === "accept") {
|
|
420
|
+
const opts = options(e, 3, ["decision", "by", "id", "revoke", "reason"]), target = instance(xs[1]), component = ir.components.find((c) => c.name === target.component), requirement = component.requirements.find((r) => r.name === name(xs[2]));
|
|
421
|
+
if (!requirement?.accepts)
|
|
422
|
+
return reference("Use a requirement that accepts prior evidence.", xs[2]);
|
|
423
|
+
const decision = opts.has("decision") ? name(opts.get("decision")) : ":accepted";
|
|
424
|
+
if (decision !== ":accepted" && decision !== ":declined")
|
|
425
|
+
return mismatch(opts.get("decision"));
|
|
426
|
+
const strings = {};
|
|
427
|
+
for (const key of ["id", "revoke"])
|
|
428
|
+
if (opts.has(key)) {
|
|
429
|
+
const v = opts.get(key);
|
|
430
|
+
if (v._tag !== "Str" || !v.value.trim())
|
|
431
|
+
return mismatch(v);
|
|
432
|
+
strings[key] = v.value;
|
|
433
|
+
}
|
|
434
|
+
const contract = ir.decisions?.find((d) => d.name ===
|
|
435
|
+
priorCycleOperationName(ir.decisions ?? [], component.name, requirement.accepts.with ?? requirement.name, decision.slice(1)));
|
|
436
|
+
if (opts.has("reason")) {
|
|
437
|
+
const reason = value(opts.get("reason"), contract?.reason ?? ["Option", "String"]);
|
|
438
|
+
if (reason.k !== "literal")
|
|
439
|
+
return mismatch(opts.get("reason"));
|
|
440
|
+
strings.reason = reason.value;
|
|
441
|
+
}
|
|
442
|
+
return {
|
|
443
|
+
...strings,
|
|
444
|
+
kind,
|
|
445
|
+
target,
|
|
446
|
+
requirement: requirement.name,
|
|
447
|
+
decision: decision.slice(1),
|
|
448
|
+
by: actor(opts.get("by")),
|
|
449
|
+
at: at(e),
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
if (kind !== "perform")
|
|
453
|
+
return shape("Use set, perform, accept, evidence or signal commands.", e);
|
|
454
|
+
const opts = options(e, 3, ["by", "unsigned", "values", "signature", "amend"]), target = instance(xs[1]), component = ir.components.find((c) => c.name === target.component), action = component.actions.find((a) => a.name === name(xs[2]));
|
|
455
|
+
if (!action)
|
|
456
|
+
return reference("Unknown component action.", xs[2]);
|
|
457
|
+
const unsigned = opts.get("unsigned");
|
|
458
|
+
if (unsigned && unsigned._tag !== "Bool")
|
|
459
|
+
return mismatch(unsigned);
|
|
460
|
+
const rawAmend = opts.get("amend");
|
|
461
|
+
let amend;
|
|
462
|
+
if (rawAmend) {
|
|
463
|
+
if (rawAmend._tag !== "Map" || rawAmend.pairs.length !== 2)
|
|
464
|
+
return mismatch(rawAmend);
|
|
465
|
+
const values = new Map(rawAmend.pairs.map(([key, value]) => [name(key), value]));
|
|
466
|
+
const previous = values.get(":previous"), reason = values.get(":reason");
|
|
467
|
+
if (previous?._tag !== "Str" || reason?._tag !== "Str")
|
|
468
|
+
return mismatch(rawAmend);
|
|
469
|
+
amend = { previous: previous.value, reason: reason.value };
|
|
470
|
+
}
|
|
471
|
+
const rawSignature = opts.get("signature");
|
|
472
|
+
let signature;
|
|
473
|
+
if (rawSignature) {
|
|
474
|
+
if (rawSignature._tag !== "Map" || rawSignature.pairs.length !== 4)
|
|
475
|
+
return mismatch(rawSignature);
|
|
476
|
+
const values = new Map(rawSignature.pairs.map(([key, value]) => [name(key), value]));
|
|
477
|
+
const consent = values.get(":consent"), intent = values.get(":intent"), method = values.get(":method"), device = values.get(":device");
|
|
478
|
+
if (consent?._tag !== "Bool" ||
|
|
479
|
+
intent?._tag !== "Bool" ||
|
|
480
|
+
method?._tag !== "Str" ||
|
|
481
|
+
device?._tag !== "Str")
|
|
482
|
+
return mismatch(rawSignature);
|
|
483
|
+
signature = {
|
|
484
|
+
consent: consent.value,
|
|
485
|
+
intent: intent.value,
|
|
486
|
+
method: method.value,
|
|
487
|
+
device: device.value,
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
const via = action.via;
|
|
491
|
+
const interaction = via.kind === "interaction"
|
|
492
|
+
? ir.interactions.find((i) => i.name === via.name)
|
|
493
|
+
: undefined;
|
|
494
|
+
const evidence = interaction && ir.evidence.find((v) => v.name === interaction.produces);
|
|
495
|
+
return {
|
|
496
|
+
kind,
|
|
497
|
+
target,
|
|
498
|
+
action: action.name,
|
|
499
|
+
by: actor(opts.get("by")),
|
|
500
|
+
unsigned: unsigned?._tag === "Bool" ? unsigned.value : false,
|
|
501
|
+
...(signature ? { signature } : {}),
|
|
502
|
+
...(amend ? { amend } : {}),
|
|
503
|
+
values: fields(opts.get("values"), evidence?.fields ?? []),
|
|
504
|
+
at: at(e),
|
|
505
|
+
};
|
|
506
|
+
};
|
|
507
|
+
const files = declarations
|
|
508
|
+
.filter((e) => head(e) === "file")
|
|
509
|
+
.map((e) => {
|
|
510
|
+
const xs = list(e), digest = xs[1], opts = options(e, 2, ["home", "media-type", "size", "scan", "redacted", "on"]), home = opts.get("home"), media = opts.get("media-type"), size = opts.get("size"), scan = opts.get("scan"), redacted = opts.get("redacted");
|
|
511
|
+
if (digest?._tag !== "Str" || !fileDigest(digest.value))
|
|
512
|
+
return mismatch(digest);
|
|
513
|
+
if (!local.has(name(home) ?? ""))
|
|
514
|
+
return reference("File metadata needs a given entity home.", home);
|
|
515
|
+
if (media?._tag !== "Str" || !fileMediaType(media.value))
|
|
516
|
+
return mismatch(media);
|
|
517
|
+
if (size?._tag !== "Num" ||
|
|
518
|
+
!Number.isSafeInteger(Number(size.value)) ||
|
|
519
|
+
Number(size.value) < 0)
|
|
520
|
+
return mismatch(size);
|
|
521
|
+
const state = scan ? name(scan)?.replace(/^:/, "") : "pending";
|
|
522
|
+
if (!state || !["pending", "clean", "rejected"].includes(state))
|
|
523
|
+
return mismatch(scan);
|
|
524
|
+
if (redacted && redacted._tag !== "Bool")
|
|
525
|
+
return mismatch(redacted);
|
|
526
|
+
return {
|
|
527
|
+
home: name(home),
|
|
528
|
+
digest: digest.value,
|
|
529
|
+
mediaType: media.value,
|
|
530
|
+
size: Number(size.value),
|
|
531
|
+
scan: state,
|
|
532
|
+
redacted: redacted?._tag === "Bool" ? redacted.value : false,
|
|
533
|
+
...(opts.has("on") ? { date: readDate(opts.get("on")) } : {}),
|
|
534
|
+
at: at(e),
|
|
535
|
+
};
|
|
536
|
+
});
|
|
537
|
+
const records = declarations
|
|
538
|
+
.filter((e) => head(e) !== "entity" && head(e) !== "actor" && head(e) !== "file")
|
|
539
|
+
.map(record);
|
|
540
|
+
let pending = [];
|
|
541
|
+
let previous;
|
|
542
|
+
const steps = [];
|
|
543
|
+
for (const block of blocks) {
|
|
544
|
+
if (head(block) === "given")
|
|
545
|
+
continue;
|
|
546
|
+
if (head(block) === "do") {
|
|
547
|
+
pending.push(...list(block).slice(1).map(command));
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
550
|
+
if (head(block) !== "at")
|
|
551
|
+
shape("Expected a dated at block.", block);
|
|
552
|
+
const xs = list(block), current = readDate(xs[1]);
|
|
553
|
+
if (previous && timePointKey(current) < timePointKey(previous))
|
|
554
|
+
fail("E_SCENARIO_DATE", "Scenario dates must be nondecreasing.", xs[1], "Order at blocks from earliest to latest; historical fact dates are data, not clock rewinds.");
|
|
555
|
+
previous = current;
|
|
556
|
+
const expects = xs.slice(2).map((e) => {
|
|
557
|
+
const parts = list(e), selector = list(parts[1]), kind = name(selector[0]);
|
|
558
|
+
if (head(e) !== "expect" || parts.length !== 3)
|
|
559
|
+
return shape("Use (expect (selector ...) expected).", e);
|
|
560
|
+
if (kind === "property") {
|
|
561
|
+
if (selector.length !== 4 || name(selector[2]) !== ":for")
|
|
562
|
+
return shape("Use (property name :for given-alias).", selector[2] ?? parts[1]);
|
|
563
|
+
const property = ir.properties?.find((p) => p.name === name(selector[1]) && p.world === account.name);
|
|
564
|
+
if (!property)
|
|
565
|
+
return reference("Unknown property in this world.", selector[1]);
|
|
566
|
+
const alias = name(selector[3]), entity = local.get(alias ?? "");
|
|
567
|
+
if (!entity)
|
|
568
|
+
return reference("Unknown given alias for this property.", selector[3]);
|
|
569
|
+
if (entity.name !== property.binding.entity)
|
|
570
|
+
return mismatch(selector[3]);
|
|
571
|
+
if (current !== property.date)
|
|
572
|
+
return fail("E_SCENARIO_DATE", "Property replay must use its fixed date.", xs[1], `Observe this property on ${property.date}.`);
|
|
573
|
+
if (parts[2]?._tag !== "Bool")
|
|
574
|
+
return mismatch(parts[2]);
|
|
575
|
+
return {
|
|
576
|
+
kind,
|
|
577
|
+
name: property.name,
|
|
578
|
+
binding: alias,
|
|
579
|
+
expected: parts[2].value,
|
|
580
|
+
at: at(e),
|
|
581
|
+
};
|
|
582
|
+
}
|
|
583
|
+
if (kind === "rejected") {
|
|
584
|
+
if (selector.length !== 2)
|
|
585
|
+
return shape("Use (rejected N) with the one-based command index in this observation.", parts[1]);
|
|
586
|
+
const n = selector[1];
|
|
587
|
+
if (n?._tag !== "Num" ||
|
|
588
|
+
!Number.isSafeInteger(Number(n.value)) ||
|
|
589
|
+
Number(n.value) < 1)
|
|
590
|
+
return mismatch(n);
|
|
591
|
+
if (Number(n.value) > pending.length)
|
|
592
|
+
return reference("No command with this index in the dated block.", n);
|
|
593
|
+
const expected = parts[2];
|
|
594
|
+
if (expected._tag !== "Bool" && !name(expected)?.startsWith(":"))
|
|
595
|
+
return mismatch(expected);
|
|
596
|
+
return {
|
|
597
|
+
kind,
|
|
598
|
+
command: Number(n.value),
|
|
599
|
+
expected: expected._tag === "Bool" ? expected.value : name(expected).slice(1),
|
|
600
|
+
at: at(e),
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
if (kind === "retention") {
|
|
604
|
+
if (selector.length !== 3)
|
|
605
|
+
return shape("Use (retention occurrence until|eligible).", parts[1]);
|
|
606
|
+
const target = instance(selector[1]), component = ir.components.find((c) => c.name === target.component), field = name(selector[2]), expected = parts[2];
|
|
607
|
+
if (!component.retention)
|
|
608
|
+
return reference("This component has no retention declaration.", selector[1]);
|
|
609
|
+
if (field !== "until" && field !== "eligible")
|
|
610
|
+
return reference("Select retention until or eligible.", selector[2]);
|
|
611
|
+
if (field === "eligible" && name(expected) !== "nil" && expected._tag !== "Bool")
|
|
612
|
+
return mismatch(expected);
|
|
613
|
+
return {
|
|
614
|
+
kind,
|
|
615
|
+
target,
|
|
616
|
+
name: "retention",
|
|
617
|
+
field,
|
|
618
|
+
expected: name(expected) === "nil"
|
|
619
|
+
? null
|
|
620
|
+
: field === "until"
|
|
621
|
+
? readDate(expected)
|
|
622
|
+
: expected._tag === "Bool"
|
|
623
|
+
? expected.value
|
|
624
|
+
: null,
|
|
625
|
+
at: at(e),
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
if (selector.length !== 3 ||
|
|
629
|
+
!["status", "due", "work", "why", "blocked", "resource"].includes(kind ?? ""))
|
|
630
|
+
return shape("Select status, due, work, why or blocked on an occurrence and clause.", e);
|
|
631
|
+
const target = instance(selector[1]), component = ir.components.find((c) => c.name === target.component), clause = name(selector[2]);
|
|
632
|
+
if (kind === "resource") {
|
|
633
|
+
if (!component.resources?.some((r) => r.name === clause))
|
|
634
|
+
return reference("Unknown component resource.", selector[2]);
|
|
635
|
+
const expected = name(parts[2]);
|
|
636
|
+
if (!expected?.startsWith(":") ||
|
|
637
|
+
![
|
|
638
|
+
"acquire",
|
|
639
|
+
"release",
|
|
640
|
+
"acquiring",
|
|
641
|
+
"acquired",
|
|
642
|
+
"releasing",
|
|
643
|
+
"released",
|
|
644
|
+
"failed",
|
|
645
|
+
"uncertain",
|
|
646
|
+
"timed-out",
|
|
647
|
+
"waiting",
|
|
648
|
+
"unknown",
|
|
649
|
+
"absent",
|
|
650
|
+
].includes(expected.slice(1)))
|
|
651
|
+
return mismatch(parts[2]);
|
|
652
|
+
return {
|
|
653
|
+
kind,
|
|
654
|
+
target,
|
|
655
|
+
name: clause,
|
|
656
|
+
expected: expected.slice(1),
|
|
657
|
+
at: at(e),
|
|
658
|
+
};
|
|
659
|
+
}
|
|
660
|
+
if (kind === "work") {
|
|
661
|
+
const prior = clause?.startsWith("accept-prior:") &&
|
|
662
|
+
component.requirements.some((r) => r.name === clause.slice(13) && r.accepts?.from);
|
|
663
|
+
const reuse = clause?.startsWith("accept-reuse:") &&
|
|
664
|
+
component.requirements.some((r) => r.name === clause.slice(13) && r.reuse?.confirm);
|
|
665
|
+
if (!component.actions.some((a) => a.name === clause) && !prior && !reuse)
|
|
666
|
+
return reference("Unknown scenario action.", selector[2]);
|
|
667
|
+
const expected = parts[2];
|
|
668
|
+
if (expected?._tag !== "Map" || expected.pairs.length !== 1)
|
|
669
|
+
return shape("Work expects {:state :eligible|:waiting|:dispatched|:held|:absent}.", expected);
|
|
670
|
+
const pair = expected.pairs[0];
|
|
671
|
+
if (name(pair[0]) !== ":state")
|
|
672
|
+
return shape("Use :state in a work expectation.", pair[0]);
|
|
673
|
+
const state = name(pair[1]);
|
|
674
|
+
if (!state?.startsWith(":") ||
|
|
675
|
+
!["eligible", "waiting", "dispatched", "held", "absent"].includes(state.slice(1)))
|
|
676
|
+
return mismatch(pair[1]);
|
|
677
|
+
return {
|
|
678
|
+
kind,
|
|
679
|
+
target,
|
|
680
|
+
name: clause,
|
|
681
|
+
expected: state.slice(1),
|
|
682
|
+
at: at(e),
|
|
683
|
+
};
|
|
684
|
+
}
|
|
685
|
+
if (!component.requirements.some((r) => r.name === clause) &&
|
|
686
|
+
!(kind === "status" && component.outputs.some((o) => o.name === clause)))
|
|
687
|
+
return reference("Unknown scenario requirement/output.", selector[2]);
|
|
688
|
+
if (kind === "due")
|
|
689
|
+
return {
|
|
690
|
+
kind,
|
|
691
|
+
target,
|
|
692
|
+
name: clause,
|
|
693
|
+
expected: name(parts[2]) === "nil" ? null : readDate(parts[2]),
|
|
694
|
+
at: at(e),
|
|
695
|
+
};
|
|
696
|
+
if (kind === "why") {
|
|
697
|
+
if (parts[2]?._tag !== "Str" || !parts[2].value.trim())
|
|
698
|
+
return mismatch(parts[2]);
|
|
699
|
+
return { kind, target, name: clause, expected: parts[2].value, at: at(e) };
|
|
700
|
+
}
|
|
701
|
+
if (kind === "blocked") {
|
|
702
|
+
if (parts[2]?._tag !== "Bool")
|
|
703
|
+
return mismatch(parts[2]);
|
|
704
|
+
return { kind, target, name: clause, expected: parts[2].value, at: at(e) };
|
|
705
|
+
}
|
|
706
|
+
const status = name(parts[2]);
|
|
707
|
+
if (!status?.startsWith(":") ||
|
|
708
|
+
!["Unknown", "NotApplicable", "Open", "Overdue", "Satisfied", "Waived"].includes(status.slice(1)))
|
|
709
|
+
return mismatch(parts[2]);
|
|
710
|
+
return {
|
|
711
|
+
kind: "status",
|
|
712
|
+
target,
|
|
713
|
+
name: clause,
|
|
714
|
+
expected: status.slice(1),
|
|
715
|
+
at: at(e),
|
|
716
|
+
};
|
|
717
|
+
});
|
|
718
|
+
steps.push({
|
|
719
|
+
kind: "at",
|
|
720
|
+
date: current,
|
|
721
|
+
expects,
|
|
722
|
+
...(pending.length ? { commands: pending } : {}),
|
|
723
|
+
at: at(block),
|
|
724
|
+
});
|
|
725
|
+
pending = [];
|
|
726
|
+
}
|
|
727
|
+
if (pending.length)
|
|
728
|
+
shape("A do block needs a following dated at block.", blocks.at(-1));
|
|
729
|
+
if (!steps.length)
|
|
730
|
+
shape("A scenario needs at least one dated assertion block.");
|
|
731
|
+
const xs = list(form), doc = xs[2];
|
|
732
|
+
scenarios.push({
|
|
733
|
+
name: name(xs[1]),
|
|
734
|
+
...(doc?._tag === "Str" ? { doc: doc.value } : {}),
|
|
735
|
+
world: account.name,
|
|
736
|
+
given,
|
|
737
|
+
...(files.length ? { files } : {}),
|
|
738
|
+
...(actors.length ? { actors } : {}),
|
|
739
|
+
...(records.length ? { records } : {}),
|
|
740
|
+
steps,
|
|
741
|
+
at: at(),
|
|
742
|
+
});
|
|
743
|
+
}
|
|
744
|
+
catch (error) {
|
|
745
|
+
if (!(error instanceof InvalidScenario))
|
|
746
|
+
throw error;
|
|
747
|
+
diagnostics.push({
|
|
748
|
+
code: error.code,
|
|
749
|
+
severity: "error",
|
|
750
|
+
message: error.message,
|
|
751
|
+
at: error.at,
|
|
752
|
+
help: error.help,
|
|
753
|
+
});
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
return { scenarios, diagnostics };
|
|
757
|
+
};
|