@reventlessdev/reventless-core 3.0.0-alpha.300 → 3.0.0-alpha.301

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 (60) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +3 -3
  3. package/package.json +9 -9
  4. package/src/{Behavior.res → Decision.res} +1 -1
  5. package/src/Message.res +1 -1
  6. package/src/ResourceAttribution.res +8 -8
  7. package/src/adapter/Auth/Auth_ActiveRole.res +1 -1
  8. package/src/adapter/Auth/Auth_RefusalVocabulary.res +1 -1
  9. package/src/adapter/EventLogProvisioning/EventLogProvisioning.res +1 -1
  10. package/src/adapter/RuntimeExtension/RuntimeExtension.res +3 -3
  11. package/src/admin/Platform_BakedManifest.res +1 -1
  12. package/src/admin/Platform_PluginStructuresApi.res +1 -1
  13. package/src/admin/UiFragmentRegistry/StateChange/{UiFragmentRegistry_Behavior.res → UiFragmentRegistry_Decision.res} +1 -1
  14. package/src/admin/UiFragmentRegistry/StateChange/{UiFragmentRegistry_Behavior.res.mjs → UiFragmentRegistry_Decision.res.mjs} +1 -1
  15. package/src/components/Aggregate/Aggregate_Builder.res +2 -2
  16. package/src/components/Aggregate/Aggregate_Builder.res.mjs +2 -2
  17. package/src/components/Aggregate/Aggregate_Callback.res +17 -17
  18. package/src/components/Aggregate/Aggregate_Callback.res.mjs +11 -11
  19. package/src/components/Api/ApiNoApiHelpers.res +1 -1
  20. package/src/components/Api/GraphQL_FragmentGenerator.res +1 -1
  21. package/src/components/Api/SchemaType.res +1 -1
  22. package/src/components/CommandTopic/CommandTopic_Helpers.res +4 -4
  23. package/src/components/EventLog/EventLog_Operations.res +2 -2
  24. package/src/components/StateChangeSlice/StateChangeSlice.res +1 -1
  25. package/src/components/StateChangeSlice/StateChangeSlice_Builder.res +3 -3
  26. package/src/components/StateChangeSlice/StateChangeSlice_Builder.res.mjs +3 -3
  27. package/src/components/StateChangeSlice/StateChangeSlice_Callback.res +9 -9
  28. package/src/components/StateChangeSlice/StateChangeSlice_Callback.res.mjs +4 -4
  29. package/src/plugin/component/Plugin_Structure.res +1 -1
  30. package/src/plugin/lifecycle/{PluginBehavior.res → PluginDecision.res} +4 -4
  31. package/src/plugin/lifecycle/{PluginBehavior.res.mjs → PluginDecision.res.mjs} +1 -1
  32. package/tests/aggregate/AggregateCacheTest.res +4 -4
  33. package/tests/aggregate/AggregateCacheTest.res.mjs +2 -2
  34. package/tests/aggregate/AggregateCallbackTest.res +2 -2
  35. package/tests/aggregate/AggregateCallbackTest.res.mjs +1 -1
  36. package/tests/aggregate/AggregateConflictTest.res +4 -4
  37. package/tests/aggregate/AggregateConflictTest.res.mjs +2 -2
  38. package/tests/aggregate/AggregateFixtures.res +5 -5
  39. package/tests/aggregate/AggregateFixtures.res.mjs +2 -2
  40. package/tests/aggregate/AggregateRejectionTest.res +1 -1
  41. package/tests/aggregate/AggregateSnapshotTest.res +7 -7
  42. package/tests/aggregate/AggregateSnapshotTest.res.mjs +4 -4
  43. package/tests/api/PsInternalFieldsReadModel.res +1 -1
  44. package/tests/api/TaggedUnionSchemaTest.res +1 -1
  45. package/tests/commandgenerator/CommandGeneratorCallbackTest.res +1 -1
  46. package/tests/commandgenerator/CommandGeneratorFixtures.res +2 -2
  47. package/tests/commandgenerator/CommandGeneratorFixtures.res.mjs +2 -2
  48. package/tests/commandgenerator/OwnerActingTest.res +4 -4
  49. package/tests/commandgenerator/OwnerActingTest.res.mjs +4 -4
  50. package/tests/commandgenerator/OwnerStampingTest.res +1 -1
  51. package/tests/commandtopic/CommandOutcomeHookTest.res +2 -2
  52. package/tests/commandtopic/CommandOutcomeHookTest.res.mjs +3 -3
  53. package/tests/dcb/DcbStateChangeSliceTest.res +5 -5
  54. package/tests/dcb/DcbStateChangeSliceTest.res.mjs +5 -5
  55. package/tests/plugin/PluginStructureAccessTest.res +1 -1
  56. package/tests/plugin/PluginStructureAccessTest.res.mjs +2 -2
  57. package/tests/plugin/PluginStructureTest.res +15 -15
  58. package/tests/plugin/PluginStructureTest.res.mjs +20 -20
  59. package/tests/projection/LifecycleTrailTest.res +1 -1
  60. /package/src/{Behavior.res.mjs → Decision.res.mjs} +0 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,20 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # 3.0.0-alpha.301 (2026-10-21)
7
+
8
+ * feat!: the write-side logic module is called the decision, and a codemod moves an app over ([cb573ff](https://github.com/ReventlessDev/reventless-core/commit/cb573ff5b928c7d7f3e75988dfaa65066f8c95eb))
9
+
10
+ ### BREAKING CHANGES
11
+
12
+ * <Spec>_Behavior.res, @@reventless.behavior,
13
+ Reventless.Behavior.T, StateChangeSlice.Behavior, Behavior_GWT and
14
+ thenRefused no longer exist. Run `npx reventless-rename-to-decision` at an
15
+ app's root, then rebuild; comments are not rewritten. The PPX must be the
16
+ matching release.
17
+
18
+
19
+
6
20
  # 3.0.0-alpha.300 (2026-10-19)
7
21
 
8
22
  **Note:** Version bump only for package @reventlessdev/reventless-core
package/README.md CHANGED
@@ -10,7 +10,7 @@
10
10
  The **provider-agnostic core** of [Reventless](https://docs.reventless.dev) — a
11
11
  spec-driven, event-sourced CQRS framework written in [ReScript](https://rescript-lang.org).
12
12
  This package is the runtime you model your domain against: the type-safe building blocks
13
- for commands, events, projections, and the behaviors that evolve state — with **no** cloud
13
+ for commands, events, projections, and the decisions that evolve state — with **no** cloud
14
14
  or storage dependency. The provider-specific adapters live in separate packages
15
15
  (see [Where it fits](#where-it-fits)).
16
16
 
@@ -19,8 +19,8 @@ or storage dependency. The provider-specific adapters live in separate packages
19
19
  ReScript modules, consumed by adding the package to your `rescript.json` `dependencies`:
20
20
 
21
21
  - **`Message`** — command / event message contracts and their service interface.
22
- - **`Behavior`** — the write-side behavior spec: event-sourced state transitions
23
- (`evolve(state, event) => state`).
22
+ - **`Decision`** — the write side's decision module type (the decider pattern):
23
+ event-sourced state transitions (`evolve(state, event) => state`) and `decide`.
24
24
  - **`Projection`** / **`ProjectionMapper`** — read models projected from event streams.
25
25
  - **`Mapper`** / **`Mapper1toN`** / **`MapperNto1`** — cross-component event translation
26
26
  (encode/decode between a source and a target contract).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reventlessdev/reventless-core",
3
- "version": "3.0.0-alpha.300",
3
+ "version": "3.0.0-alpha.301",
4
4
  "description": "Core package for Reventless framework",
5
5
  "license": "Apache-2.0",
6
6
  "jest": {
@@ -28,17 +28,17 @@
28
28
  "dependencies": {
29
29
  "sury": "11.0.0",
30
30
  "uuid": "^13.0.0",
31
- "@reventlessdev/rescript-effect": "1.0.0-alpha.0",
32
- "@reventlessdev/rescript-node": "2.0.0-alpha.22",
33
- "@reventlessdev/rescript-jest": "1.0.0-alpha.12",
34
- "@reventlessdev/rescript-fast-csv": "2.0.0-alpha.22",
31
+ "@reventlessdev/rescript-fast-csv": "2.0.0-alpha.23",
32
+ "@reventlessdev/rescript-effect": "1.0.0-alpha.1",
33
+ "@reventlessdev/rescript-jest": "1.0.0-alpha.13",
34
+ "@reventlessdev/rescript-node": "2.0.0-alpha.23",
35
35
  "@reventlessdev/rescript-hash-object": "1.2.0-alpha.15",
36
36
  "@reventlessdev/rescript-pulumi-pulumi": "3.0.0-alpha.0",
37
+ "@reventlessdev/rescript-ssh2": "2.0.0-alpha.24",
38
+ "@reventlessdev/reventless-infra": "3.0.0-alpha.198",
37
39
  "@reventlessdev/rescript-uuid": "2.0.0-alpha.1",
38
- "@reventlessdev/reventless-infra": "3.0.0-alpha.197",
39
- "@reventlessdev/reventless-interop": "3.0.0-alpha.41",
40
- "@reventlessdev/reventless-spec": "3.0.0-alpha.169",
41
- "@reventlessdev/rescript-ssh2": "2.0.0-alpha.23"
40
+ "@reventlessdev/reventless-interop": "3.0.0-alpha.42",
41
+ "@reventlessdev/reventless-spec": "3.0.0-alpha.170"
42
42
  },
43
43
  "devDependencies": {
44
44
  "rescript": "12.3.1",
@@ -1,4 +1,4 @@
1
- include Reventless.Behavior
1
+ include Reventless.Decision
2
2
 
3
3
  module type Spec = {
4
4
  @schema
package/src/Message.res CHANGED
@@ -308,7 +308,7 @@ let metaKeys = [
308
308
 
309
309
  `StoredEvent` is the logical shape (nested `meta:meta`). The on-disk shape is
310
310
  a flat top-level dict so DynamoDB GSIs can project individual meta attributes
311
- (the §1.2/§3.2 behaviour today, preserved here). These two helpers are the
311
+ (the §1.2/§3.2 behavior today, preserved here). These two helpers are the
312
312
  single bridge between the two — used by both EventLog (aggregate) and
313
313
  DcbEventLog (DCB) storage paths.
314
314
  */
@@ -7,11 +7,11 @@ drifting into private spellings of the same fact.
7
7
 
8
8
  The three facts are deliberately independent:
9
9
 
10
- - `ComponentType.t` — the *modelling* kind (Aggregate, StateViewSlice, …): what
10
+ - `ComponentType.t` — the *modeling* kind (Aggregate, StateViewSlice, …): what
11
11
  the element IS in the domain model.
12
- - `Role.t` — the *deployment piece* (EventLog, QueryDb, Runtime, …): what job
13
- this particular resource does for that element. One component owns several
14
- pieces, so kind alone can't identify a resource.
12
+ - `Role.t` — the *deployment role* (EventLog, QueryDb, Runtime, …): what job
13
+ this particular resource does for that element. One component owns resources in
14
+ several roles, so kind alone can't identify a resource.
15
15
  - `Scope.t` — the level the resource is attributed to: an individual component,
16
16
  a plugin's shared substrate, or platform substrate.
17
17
 
@@ -40,8 +40,8 @@ module Scope = {
40
40
  }
41
41
 
42
42
  /**
43
- The deployment piece a resource implements. `Other(string)` is the escape hatch
44
- for support pieces and future roles (same pattern as `Monitoring.unitKind`).
43
+ The deployment role a resource plays. `Other(string)` is the escape hatch
44
+ for support roles and future ones (same pattern as `Monitoring.unitKind`).
45
45
  */
46
46
  module Role = {
47
47
  type t =
@@ -105,11 +105,11 @@ module Role = {
105
105
  /**
106
106
  The model component a provisioned resource belongs to.
107
107
 
108
- Piece builders (EventLog, QueryDb, CommandTopic, EventTopic, EventCollector) are
108
+ Role builders (EventLog, QueryDb, CommandTopic, EventTopic, EventCollector) are
109
109
  shared building blocks applied as functors by many different component kinds — a
110
110
  QueryDb is instantiated by ReadModel, StateViewSlice, AutomationSlice, both
111
111
  translation slices and Counter. The adapter that provisions the physical resource
112
- sits at the bottom of that chain and would otherwise only know its own piece, so
112
+ sits at the bottom of that chain and would otherwise only know its own role, so
113
113
  `kind` would collapse onto `role` and the owning component would be unrecoverable.
114
114
  The owning builder passes this record down instead.
115
115
 
@@ -69,7 +69,7 @@ boundary — and a table copied into two test suites is exactly the drift it exi
69
69
  to prevent.
70
70
 
71
71
  `expected` is the group set the minted token must carry. `None` means the request
72
- must be **refused** rather than honoured, ignored, or reduced to the empty set —
72
+ must be **refused** rather than honored, ignored, or reduced to the empty set —
73
73
  the distinction §3 turns on. A path with no client to refuse (the trigger, reading
74
74
  stored state) resolves `None` by minting `membership` and marking
75
75
  [staleRoleClaim]; a path answering a live request refuses it.
@@ -120,7 +120,7 @@ Classify a refusal without knowing which adapter produced it.
120
120
 
121
121
  Pass what the response actually carried: its status, the `errorType` of a GraphQL
122
122
  error if there was one, and `extensions.code` if there was one. Returns `None`
123
- when the response is not a refusal this contract recognises — which includes a
123
+ when the response is not a refusal this contract recognizes — which includes a
124
124
  successful response, so a caller must not read `None` as "allowed".
125
125
 
126
126
  Ordering matters and is the point of the function. The transport status is
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  Deploy-time hook: every event log announces itself as it is provisioned, so an
3
- extension can attach behaviour to it inside the program that owns it.
3
+ extension can attach behavior to it inside the program that owns it.
4
4
 
5
5
  No-op by default. Zero behavioral change unless an extension registers a backend
6
6
  via `use` before the platform/plugin build. The seam fires once per log at
@@ -8,7 +8,7 @@ No-op by default. Zero behavioral change unless an extension registers one via
8
8
  no code runs.
9
9
 
10
10
  `Monitoring` and `EventLogProvisioning` are the deploy-time half of this shape —
11
- they let an extension attach behaviour to *what gets provisioned*. This is the
11
+ they let an extension attach behavior to *what gets provisioned*. This is the
12
12
  runtime half: *what runs inside it*. Without it,
13
13
  `CommandGenerator_Callback.registerCommandInterceptor`,
14
14
  `QueryDb_Callback.registerQueryInterceptor` and the two
@@ -34,7 +34,7 @@ to internals would make it a second, informal handler API — and the four hooks
34
34
  exists to reach already receive their own per-request payloads
35
35
  (`commandInterceptor` gets `~componentName` / `~tag` / `~args` on every call).
36
36
 
37
- `~runtimeKind` is the modelling kind of the component the runtime runs — the same
37
+ `~runtimeKind` is the modeling kind of the component the runtime runs — the same
38
38
  `ComponentType.t` every AWS runtime builder already passes to
39
39
  `RuntimeEnvironment_Lambda.makeFromCodeAsset`, so there is no third taxonomy to
40
40
  keep in step with `Monitoring.unitKind` and `ResourceAttribution.Role`.
@@ -67,7 +67,7 @@ runtime handles its first request.
67
67
  seam reachable in a *deployed* runtime: registering a first-class module only
68
68
  populates the deploy program's process, and the Lambda is a different one, so the
69
69
  framework bundles the module's package into the code archive and names the module
70
- in the runtime's config for the entry shell to import. Spec and behavior modules
70
+ in the runtime's config for the entry shell to import. Spec and decision modules
71
71
  are carried into runtimes the same way. The convention matches
72
72
  `@@reventless.spec`'s injected `let moduleUrl`, so a ReScript extension can lift
73
73
  it from there.
@@ -57,7 +57,7 @@ let describe = (e: error): string =>
57
57
  // gives. Unlike the other two, what it selects is not filtered here — there is
58
58
  // nothing in a `pluginStructure` to filter, because the pages do not exist until
59
59
  // a shell builds them. It travels to the shell instead, which is the only place
60
- // that can honour it.
60
+ // that can honor it.
61
61
  type selection = {
62
62
  plugin: string,
63
63
  views: option<array<string>>,
@@ -43,7 +43,7 @@ let sdlTypes: array<string> = [
43
43
  // reason the capability above is: a plugin built against a newer framework,
44
44
  // naming a posture this schema has never heard of, still decodes.
45
45
  //
46
- // It records ORIGIN, never behaviour — a grafted file is the host's to edit
46
+ // It records ORIGIN, never behavior — a grafted file is the host's to edit
47
47
  // afterwards — so a reader must not paint a declared graft as a verified one.
48
48
  `type Platform_TraitDeclaration {\n trait: String!\n version: String!\n posture: String!\n component: String!\n}`,
49
49
  // `extensionPoints` / `requiredStores` / `requiredStoreDeclarations` /
@@ -1,4 +1,4 @@
1
- @@reventless.behavior
1
+ @@reventless.decision
2
2
 
3
3
  open Reventless.Plugin
4
4
 
@@ -68,7 +68,7 @@ let Spec;
68
68
 
69
69
  let initialState;
70
70
 
71
- let moduleUrl = "@reventlessdev/reventless-core/src/admin/UiFragmentRegistry/StateChange/UiFragmentRegistry_Behavior.res.mjs";
71
+ let moduleUrl = "@reventlessdev/reventless-core/src/admin/UiFragmentRegistry/StateChange/UiFragmentRegistry_Decision.res.mjs";
72
72
 
73
73
  export {
74
74
  Spec,
@@ -1,6 +1,6 @@
1
1
  module Make = (
2
2
  Spec: Reventless.Aggregate.Spec,
3
- Behavior: Behavior.T with module Spec := Spec,
3
+ Decision: Decision.T with module Spec := Spec,
4
4
  EventMappings: EventMapper.Mappings with module Target := Spec,
5
5
  RuntimeEnvironment: Runtime.Environment,
6
6
  CommandGeneratorResolvers: CommandGenerator_Adapter.Resolvers
@@ -87,7 +87,7 @@ module Make = (
87
87
  ->Pulumi.Output.apply(eventLogOps => {
88
88
  module AggregateCallback = Aggregate_Callback.Make(
89
89
  Spec,
90
- Behavior,
90
+ Decision,
91
91
  {
92
92
  module Spec = Spec
93
93
  module EventLog = SpecificEventLog
@@ -16,7 +16,7 @@ import * as CommandGenerator_Builder$ReventlessCore from "../CommandGenerator/Co
16
16
  import * as CommandGenerator_Callback$ReventlessCore from "../CommandGenerator/CommandGenerator_Callback.res.mjs";
17
17
 
18
18
  function Make(Spec) {
19
- return Behavior => (EventMappings => (RuntimeEnvironment => (CommandGeneratorResolvers => (CommandTopicChannel => (EventLogStorage => (EventTopicPublisher => (EventCollectorChannel => (AggregateRuntimeBuilder => (HooksConfig => {
19
+ return Decision => (EventMappings => (RuntimeEnvironment => (CommandGeneratorResolvers => (CommandTopicChannel => (EventLogStorage => (EventTopicPublisher => (EventCollectorChannel => (AggregateRuntimeBuilder => (HooksConfig => {
20
20
  let SpecificEventLog = EventLog_Builder$ReventlessCore.Make(Spec)(EventLogStorage)(EventTopicPublisher);
21
21
  let SpecificCommandTopic = CommandTopic_Builder$ReventlessCore.Make({
22
22
  Id: Spec.Id,
@@ -36,7 +36,7 @@ function Make(Spec) {
36
36
  name: Spec.name
37
37
  }, opts);
38
38
  return Component$ReventlessCore.operations(eventLog).apply(eventLogOps => {
39
- let AggregateCallback = Aggregate_Callback$ReventlessCore.Make(Spec)(Behavior)({
39
+ let AggregateCallback = Aggregate_Callback$ReventlessCore.Make(Spec)(Decision)({
40
40
  Spec: Spec,
41
41
  EventLog: SpecificEventLog,
42
42
  eventLog: eventLogOps
@@ -16,7 +16,7 @@ module type T = {
16
16
 
17
17
  module Make = (
18
18
  Spec: Reventless.Aggregate.Spec,
19
- Behavior: Behavior.T with module Spec := Spec,
19
+ Decision: Decision.T with module Spec := Spec,
20
20
  Ops: Ops with module Spec = Spec,
21
21
  ): (T with module Spec = Spec) => {
22
22
  module Spec = Spec
@@ -82,9 +82,9 @@ module Make = (
82
82
  | CmdRefused(CommandTopic_Helpers.ownershipRefusal)
83
83
 
84
84
  // Folds a single command into the running accumulator: (currentState, perCommandOutcomes).
85
- // A domain rejection from Behavior.decide is recorded as `CmdRejected` (no state change,
85
+ // A domain rejection from Decision.decide is recorded as `CmdRejected` (no state change,
86
86
  // surviving commands in the batch continue); a successful decide records `CmdOk(events)`
87
- // and advances state via `Behavior.evolve`.
87
+ // and advances state via `Decision.evolve`.
88
88
  //
89
89
  // `~seq` is the replayed sequence number the batch decides from, carried in so
90
90
  // the line below can name the state rather than serialise it.
@@ -94,7 +94,7 @@ module Make = (
94
94
  let processCommand = (~seq: int) =>
95
95
  (
96
96
  (state, owners, outcomes): (
97
- Behavior.state,
97
+ Decision.state,
98
98
  array<string>,
99
99
  array<(string, cmdOutcome, Message.meta)>,
100
100
  ),
@@ -131,9 +131,9 @@ module Make = (
131
131
  )->Effect.runSync
132
132
  (state, owners, Array.concat(outcomes, [(reference, CmdRefused(refused), meta)]))
133
133
  | None =>
134
- switch Behavior.decide(state, command'.command) {
134
+ switch Decision.decide(state, command'.command) {
135
135
  | Ok(generatedEvents) =>
136
- let newState = generatedEvents->Array.reduce(state, Behavior.evolve)
136
+ let newState = generatedEvents->Array.reduce(state, Decision.evolve)
137
137
  (
138
138
  newState,
139
139
  generatedEvents->Array.reduce(owners, recordEventOwners),
@@ -179,7 +179,7 @@ module Make = (
179
179
  // the fixed capacity (a per-aggregate knob is a future refinement — see
180
180
  // docs/plans/done/aggregate-snapshotting.md).
181
181
  let replayCacheCapacity = 100
182
- let replayCache: Lru.t<string, (Behavior.state, int, array<string>)> = Lru.make(
182
+ let replayCache: Lru.t<string, (Decision.state, int, array<string>)> = Lru.make(
183
183
  ~capacity=replayCacheCapacity,
184
184
  )
185
185
 
@@ -195,8 +195,8 @@ module Make = (
195
195
  // Off for an owner-marked aggregate: a snapshot holds the state alone, so a
196
196
  // replay seeded from one would never see the event that recorded the owner,
197
197
  // and the ownership check would pass every caller.
198
- let snapshotConfig = actsOnOwned ? None : Behavior.snapshot
199
- if actsOnOwned && Behavior.snapshot->Option.isSome {
198
+ let snapshotConfig = actsOnOwned ? None : Decision.snapshot
199
+ if actsOnOwned && Decision.snapshot->Option.isSome {
200
200
  EffectLogger.logWarn(
201
201
  ~comp,
202
202
  "snapshots disabled: this aggregate records an @owner, which a snapshot does not carry",
@@ -223,7 +223,7 @@ module Make = (
223
223
  // State ⇄ JSON via the configured stateSchema. Both swallow sury failures to
224
224
  // `None` — an unserializable state just skips the snapshot write, and an
225
225
  // undecodable snapshot falls back to full replay; neither can fail a command.
226
- let encodeState = (state: Behavior.state): option<JSON.t> =>
226
+ let encodeState = (state: Decision.state): option<JSON.t> =>
227
227
  switch snapshotConfig {
228
228
  | Some({stateSchema}) =>
229
229
  switch state->Reventless.Util_Sury.toJson(stateSchema) {
@@ -233,7 +233,7 @@ module Make = (
233
233
  | None => None
234
234
  }
235
235
 
236
- let decodeState = (json: JSON.t): option<Behavior.state> =>
236
+ let decodeState = (json: JSON.t): option<Decision.state> =>
237
237
  switch snapshotConfig {
238
238
  | Some({stateSchema}) =>
239
239
  switch json->Reventless.Util_Sury.fromJson(stateSchema) {
@@ -250,7 +250,7 @@ module Make = (
250
250
  let coldReadState = id => {
251
251
  let idStr = id->Spec.Id.toString
252
252
  let seedEffect = switch snapshotConfig {
253
- | None => Effect.succeed((Behavior.initialState, 0))
253
+ | None => Effect.succeed((Decision.initialState, 0))
254
254
  | Some(_) =>
255
255
  Effect.promise(() => Ops.eventLog.latestSnapshot(id))->Effect.map(snapResult =>
256
256
  switch snapResult {
@@ -262,28 +262,28 @@ module Make = (
262
262
  ~comp,
263
263
  `snapshot ignored (undecodable): id=${idStr}, seq=${snap.seqNr->Int.toString} — full replay`,
264
264
  )->Effect.runSync
265
- (Behavior.initialState, 0)
265
+ (Decision.initialState, 0)
266
266
  }
267
267
  | Ok(Some(snap)) =>
268
268
  EffectLogger.logWarn(
269
269
  ~comp,
270
270
  `snapshot ignored (schema drift): id=${idStr}, seq=${snap.EventLog.seqNr->Int.toString} — full replay`,
271
271
  )->Effect.runSync
272
- (Behavior.initialState, 0)
273
- | Ok(None) => (Behavior.initialState, 0)
272
+ (Decision.initialState, 0)
273
+ | Ok(None) => (Decision.initialState, 0)
274
274
  | Error(msg) =>
275
275
  EffectLogger.logWarn(
276
276
  ~comp,
277
277
  `snapshot read failed (ignored): id=${idStr}: ${msg} — full replay`,
278
278
  )->Effect.runSync
279
- (Behavior.initialState, 0)
279
+ (Decision.initialState, 0)
280
280
  }
281
281
  )
282
282
  }
283
283
  seedEffect->Effect.flatMap(((seedState, seedSeq)) =>
284
284
  Ops.eventLog.replayStream(id, ~fromSeq=seedSeq)
285
285
  ->Stream.runFold((seedState, seedSeq, []), ((st, n, owners), ev) => (
286
- Behavior.evolve(st, ev),
286
+ Decision.evolve(st, ev),
287
287
  n + 1,
288
288
  owners->recordEventOwners(ev),
289
289
  ))
@@ -20,7 +20,7 @@ import * as SchemaWalker$ReventlessCore from "../../plugin/component/SchemaWalke
20
20
  import * as CommandTopic_Helpers$ReventlessCore from "../CommandTopic/CommandTopic_Helpers.res.mjs";
21
21
 
22
22
  function Make(Spec) {
23
- return Behavior => (Ops => {
23
+ return Decision => (Ops => {
24
24
  let comp = `Aggregate(` + Spec.name + `)`;
25
25
  let groupTopicItemsByIdStream = stream => Effect.map(Stream.runFold(stream, {}, (dict, item) => {
26
26
  let id = Spec.Id.toString(item.command.id);
@@ -73,10 +73,10 @@ function Make(Spec) {
73
73
  ]])
74
74
  ];
75
75
  }
76
- let generatedEvents = Behavior.decide(state, command$p.command);
76
+ let generatedEvents = Decision.decide(state, command$p.command);
77
77
  if (generatedEvents.TAG === "Ok") {
78
78
  let generatedEvents$1 = generatedEvents._0;
79
- let newState = Stdlib_Array.reduce(generatedEvents$1, state, Behavior.evolve);
79
+ let newState = Stdlib_Array.reduce(generatedEvents$1, state, Decision.evolve);
80
80
  return [
81
81
  newState,
82
82
  Stdlib_Array.reduce(generatedEvents$1, owners, recordEventOwners),
@@ -112,8 +112,8 @@ function Make(Spec) {
112
112
  });
113
113
  let replayCache = Lru$ReventlessCore.make(100);
114
114
  let resetCache = () => Lru$ReventlessCore.clear(replayCache);
115
- let snapshotConfig = actsOnOwned ? undefined : Behavior.snapshot;
116
- if (actsOnOwned && Stdlib_Option.isSome(Behavior.snapshot)) {
115
+ let snapshotConfig = actsOnOwned ? undefined : Decision.snapshot;
116
+ if (actsOnOwned && Stdlib_Option.isSome(Decision.snapshot)) {
117
117
  Effect.runSync(EffectLogger$ReventlessCore.logWarn(comp, undefined, "snapshots disabled: this aggregate records an @owner, which a snapshot does not carry"));
118
118
  }
119
119
  let stateSchemaHash = snapshotConfig !== undefined ? HashObject(Object.fromEntries([[
@@ -153,7 +153,7 @@ function Make(Spec) {
153
153
  let snap = snapResult._0;
154
154
  if (snap === undefined) {
155
155
  return [
156
- Behavior.initialState,
156
+ Decision.initialState,
157
157
  0
158
158
  ];
159
159
  }
@@ -167,24 +167,24 @@ function Make(Spec) {
167
167
  } else {
168
168
  Effect.runSync(EffectLogger$ReventlessCore.logWarn(comp, undefined, `snapshot ignored (undecodable): id=` + idStr + `, seq=` + snap.seqNr.toString() + ` — full replay`));
169
169
  return [
170
- Behavior.initialState,
170
+ Decision.initialState,
171
171
  0
172
172
  ];
173
173
  }
174
174
  }
175
175
  Effect.runSync(EffectLogger$ReventlessCore.logWarn(comp, undefined, `snapshot ignored (schema drift): id=` + idStr + `, seq=` + snap.seqNr.toString() + ` — full replay`));
176
176
  return [
177
- Behavior.initialState,
177
+ Decision.initialState,
178
178
  0
179
179
  ];
180
180
  }
181
181
  Effect.runSync(EffectLogger$ReventlessCore.logWarn(comp, undefined, `snapshot read failed (ignored): id=` + idStr + `: ` + snapResult._0 + ` — full replay`));
182
182
  return [
183
- Behavior.initialState,
183
+ Decision.initialState,
184
184
  0
185
185
  ];
186
186
  }) : Effect.succeed([
187
- Behavior.initialState,
187
+ Decision.initialState,
188
188
  0
189
189
  ]);
190
190
  return Effect.flatMap(seedEffect, param => {
@@ -194,7 +194,7 @@ function Make(Spec) {
194
194
  seedSeq,
195
195
  []
196
196
  ], (param, ev) => [
197
- Behavior.evolve(param[0], ev),
197
+ Decision.evolve(param[0], ev),
198
198
  param[1] + 1 | 0,
199
199
  recordEventOwners(param[2], ev)
200
200
  ]), param => {
@@ -5,7 +5,7 @@ let isNoApi = (commandSchema: S.t<unknown>): bool =>
5
5
 
6
6
  // Variants excluded by a mark on the member itself. This is the half that
7
7
  // survives a spread: splicing copies members, not the metadata of the union they
8
- // came from, so a command a trait marked internal is only still recognisable here.
8
+ // came from, so a command a trait marked internal is only still recognizable here.
9
9
  let excludedByMembers = (commandSchema: S.t<unknown>): array<string> =>
10
10
  switch commandSchema {
11
11
  | AnyOf({anyOf}) =>
@@ -96,7 +96,7 @@ let rec fromSchemaType = (
96
96
  // names come from the schema — see `Reventless.TaggedUnion` — so the same union
97
97
  // is the same type wherever it appears, which is what lets AppSync merge each
98
98
  // source API's copy back into one, and what lets the write path stamp a
99
- // `__typename` the SDL will recognise.
99
+ // `__typename` the SDL will recognize.
100
100
  | TaggedUnion(name, arms) =>
101
101
  if asInput {
102
102
  // GraphQL has no input unions. A command that wants one takes its arms as
@@ -421,7 +421,7 @@ let trailShape = (
421
421
  let shape = ArrayOf(ObjectRef(entryName, fields))
422
422
  // Walking the entries by shape skips the semantic dispatch `fromSury` does,
423
423
  // so the marker is re-applied here. Without it the trail reaches a consumer
424
- // as an unremarkable array of objects, and recognising it would come down to
424
+ // as an unremarkable array of objects, and recognizing it would come down to
425
425
  // the field's name.
426
426
  switch Reventless.Semantic.get(schema) {
427
427
  | Some(sem) => Semantic(sem, shape)
@@ -12,7 +12,7 @@ during inline `publishJsonsAndWait` execution and read by `runInlineAndCollect`
12
12
  type acceptedResult = {entityId?: string, eventCount: int}
13
13
 
14
14
  /**
15
- Carries an encoded domain rejection from `Behavior.decide` back to a synchronous producer.
15
+ Carries an encoded domain rejection from `Decision.decide` back to a synchronous producer.
16
16
  `errorCode` is the variant tag of `Spec.errorSchema` (e.g. `"AlreadyExists"`); `errorDetail`
17
17
  is the JSON-stringified error payload (or empty string for payload-less variants).
18
18
  */
@@ -21,7 +21,7 @@ type rejectedResult = {errorCode: string, errorDetail: string}
21
21
  /**
22
22
  Why a command was refused.
23
23
 
24
- `DomainRejection` is `Behavior.decide` returning `Error` — the model declining the command,
24
+ `DomainRejection` is `Decision.decide` returning `Error` — the model declining the command,
25
25
  which is the model working. `InfrastructureFailure` is the decision never landing: an event-log
26
26
  append that failed outright or exhausted its conflict retries. Both arrive on `reportRejected`,
27
27
  so without this a consumer would read a broken event log as a business rejection.
@@ -92,7 +92,7 @@ let fireCommandOutcome = (~component: string, ~reference: string, outcome: obser
92
92
  let acceptedResultChannel: ref<option<(string, acceptedResult) => unit>> = ref(None)
93
93
 
94
94
  // Sibling side-channel for domain rejections — populated by callbacks when
95
- // `Behavior.decide` returns `Error`. Read by runInlineAndCollect to build
95
+ // `Decision.decide` returns `Error`. Read by runInlineAndCollect to build
96
96
  // `Rejected` outcomes that carry the real error code and detail.
97
97
  let rejectedResultChannel: ref<option<(string, rejectedResult) => unit>> = ref(None)
98
98
 
@@ -234,7 +234,7 @@ let runInlineAndCollect = async (
234
234
  rejectedResultChannel.contents = None
235
235
  jsons->Array.mapWithIndex((cmdJson, i) => {
236
236
  let msgId = cmdJson.meta.msgId
237
- // Domain rejection from Behavior.decide takes precedence over both Accepted
237
+ // Domain rejection from Decision.decide takes precedence over both Accepted
238
238
  // and the synthesized "Conflict" — it carries the most informative error.
239
239
  switch rejectedResults->Dict.get(msgId) {
240
240
  | Some({errorCode, errorDetail}) =>
@@ -17,8 +17,8 @@ module type T = {
17
17
 
18
18
  // Retry schedule for transient storage errors.
19
19
  // Exponential backoff: 100ms, ~200ms, ~400ms, ~800ms, ~1600ms — max 5 retries.
20
- // Only retries on recognised transient error messages; permanent errors propagate immediately.
21
- // Retry only recognised transient storage failures — never a Conflict (a retry
20
+ // Only retries on recognized transient error messages; permanent errors propagate immediately.
21
+ // Retry only recognized transient storage failures — never a Conflict (a retry
22
22
  // of the same append would just conflict again; the OCC retry happens a layer up
23
23
  // via replay+re-decide).
24
24
  let isTransient = (e: EventLog.appendError) =>
@@ -17,7 +17,7 @@ let toResolvedOutputs = (outputs: outputs): Pulumi.Output.t<
17
17
 
18
18
  module type T = {
19
19
  module Spec: Reventless.StateChangeSlice.Spec
20
- module Behavior: Reventless.StateChangeSlice.Behavior with module Spec := Spec
20
+ module Decision: Reventless.StateChangeSlice.Decision with module Spec := Spec
21
21
  /** `true` when built with `Platform.StateChangeSlice.MakeAsync` — uses FIFO channel, returns `CommandPending`. */
22
22
  let isAsync: bool
23
23
  type component = Component.t<t, outputs, operations>
@@ -2,13 +2,13 @@ let log = Logger.fromEnv()
2
2
 
3
3
  module Make = (
4
4
  Spec: Reventless.StateChangeSlice.Spec,
5
- Behavior: Reventless.StateChangeSlice.Behavior with module Spec := Spec,
5
+ Decision: Reventless.StateChangeSlice.Decision with module Spec := Spec,
6
6
  ): StateChangeSlice.T => {
7
7
  module Spec = Spec
8
- module Behavior = Behavior
8
+ module Decision = Decision
9
9
  let isAsync = false
10
10
  type component = StateChangeSlice.component
11
- module Callback = StateChangeSlice_Callback.Make(Spec, Behavior)
11
+ module Callback = StateChangeSlice_Callback.Make(Spec, Decision)
12
12
 
13
13
  let makeJsonHandler = (
14
14
  ~tagKeysByEventType,
@@ -16,8 +16,8 @@ import * as StateChangeSlice_Callback$ReventlessCore from "./StateChangeSlice_Ca
16
16
  let log = Logger$ReventlessCore.fromEnv();
17
17
 
18
18
  function Make(Spec) {
19
- return Behavior => {
20
- let Callback = StateChangeSlice_Callback$ReventlessCore.Make(Spec)(Behavior);
19
+ return Decision => {
20
+ let Callback = StateChangeSlice_Callback$ReventlessCore.Make(Spec)(Decision);
21
21
  let makeJsonHandler = (tagKeysByEventType, crossPartitionTagKeys, partitionTag, dcbEventLogOps) => (stream => {
22
22
  let decodedStream = Stream.flatMap(Stream.mapEffect(stream, param => {
23
23
  let reference = param.reference;
@@ -67,7 +67,7 @@ function Make(Spec) {
67
67
  };
68
68
  return {
69
69
  Spec: Spec,
70
- Behavior: Behavior,
70
+ Decision: Decision,
71
71
  isAsync: false,
72
72
  make: make
73
73
  };