@reventlessdev/reventless-spec 3.0.0-alpha.169 → 3.0.0-alpha.171

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 (43) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +17 -3
  3. package/package.json +5 -4
  4. package/run-rename-to-decision.mjs +3 -0
  5. package/src/AnsiStyle.res +3 -3
  6. package/src/CliArgs.res +1 -1
  7. package/src/LogPrefix.res +1 -1
  8. package/src/codemod/RenameToDecision.res +207 -0
  9. package/src/codemod/RenameToDecision.res.mjs +334 -0
  10. package/src/components/Aggregate.res +1 -1
  11. package/src/components/CapabilityManifest.res +1 -1
  12. package/src/components/ComponentKind.res +2 -2
  13. package/src/components/ComponentKind.res.mjs +1 -1
  14. package/src/components/DcbScopeInference.res +2 -2
  15. package/src/components/DcbTag.res +5 -5
  16. package/src/components/OutboundTranslationSlice.res +2 -2
  17. package/src/components/Plugin.res +14 -14
  18. package/src/components/Plugin.res.mjs +8 -8
  19. package/src/components/Sensitive.res +1 -1
  20. package/src/components/Snapshot.res +5 -5
  21. package/src/components/StateAnnotations.res +1 -1
  22. package/src/components/StateChangeSlice.res +6 -5
  23. package/src/components/StateViewSlice.res +3 -3
  24. package/src/components/TaggedUnion.res +1 -1
  25. package/src/generator/Codegen.res +5 -5
  26. package/src/generator/Codegen.res.mjs +1 -1
  27. package/src/generator/Discovery.res +3 -3
  28. package/src/generator/Pairing.res +47 -18
  29. package/src/generator/Pairing.res.mjs +41 -10
  30. package/src/lifecycle/CheckLifecycleModel.res +8 -7
  31. package/src/lifecycle/CheckLifecycleModel.res.mjs +2 -2
  32. package/src/semantic/Capabilities.res +2 -2
  33. package/src/semantic/CapabilityNeed.res +3 -3
  34. package/src/semantic/Color.res +8 -8
  35. package/src/semantic/IdentityProvider.res +1 -1
  36. package/src/semantic/Messaging.res +2 -2
  37. package/src/types/{Behavior.res → Decision.res} +10 -6
  38. package/src/types/Message.res +1 -1
  39. package/src/types/OwnerScope.res +5 -5
  40. package/src/types/RoleCoverage.res +6 -6
  41. package/src/types/RoleCoverage.res.mjs +6 -6
  42. package/src/types/Trait.res +1 -1
  43. /package/src/types/{Behavior.res.mjs → Decision.res.mjs} +0 -0
@@ -0,0 +1,334 @@
1
+ // Generated by ReScript, PLEASE EDIT WITH CARE
2
+
3
+ import * as Nodefs from "node:fs";
4
+ import * as Nodepath from "node:path";
5
+ import * as Belt_Array from "@rescript/runtime/lib/es6/Belt_Array.js";
6
+ import * as Stdlib_Array from "@rescript/runtime/lib/es6/Stdlib_Array.js";
7
+ import * as Stdlib_JsExn from "@rescript/runtime/lib/es6/Stdlib_JsExn.js";
8
+ import * as Stdlib_Option from "@rescript/runtime/lib/es6/Stdlib_Option.js";
9
+ import * as Stdlib_Result from "@rescript/runtime/lib/es6/Stdlib_Result.js";
10
+ import * as Primitive_object from "@rescript/runtime/lib/es6/Primitive_object.js";
11
+ import * as Primitive_option from "@rescript/runtime/lib/es6/Primitive_option.js";
12
+ import * as Primitive_string from "@rescript/runtime/lib/es6/Primitive_string.js";
13
+ import * as CliArgs$Reventless from "../CliArgs.res.mjs";
14
+ import * as Nodechild_process from "node:child_process";
15
+ import * as Primitive_exceptions from "@rescript/runtime/lib/es6/Primitive_exceptions.js";
16
+
17
+ let usage = `Usage: reventless-rename-to-decision [--dry-run] [<dir>]
18
+
19
+ <dir> where to start; the default is the current directory
20
+ --dry-run print what would change, change nothing
21
+
22
+ Renames every *_Behavior.res to *_Decision.res (git mv inside a git work tree,
23
+ with its compiled output beside it), and in every .res and .resi file:
24
+ @@reventless.behavior -> @@reventless.decision, Behavior_GWT -> Decision_GWT,
25
+ Reventless.Behavior -> Reventless.Decision, thenRefused -> thenForbidden, and
26
+ <Spec>_Behavior -> <Spec>_Decision. Skips node_modules and lib.`;
27
+
28
+ function parseArgs(argv) {
29
+ return Stdlib_Result.map(Stdlib_Result.flatMap(CliArgs$Reventless.parse(undefined, ["dry-run"], undefined, undefined, argv), a => CliArgs$Reventless.atMost(a, 1)), a => ({
30
+ dir: Stdlib_Option.getOr(CliArgs$Reventless.positionals(a)[0], "."),
31
+ dryRun: CliArgs$Reventless.bool(a, "dry-run")
32
+ }));
33
+ }
34
+
35
+ let cli = {
36
+ bin: "reventless-rename-to-decision",
37
+ usage: usage,
38
+ parse: parseArgs
39
+ };
40
+
41
+ let replacements = [
42
+ [
43
+ /@@reventless\.behavior\b/g,
44
+ "@@reventless.decision"
45
+ ],
46
+ [
47
+ /\bBehavior_GWT\.BehaviorSpec\b/g,
48
+ "Decision_GWT.DecisionSpec"
49
+ ],
50
+ [
51
+ /\bBehavior_GWT\.Behavior\b/g,
52
+ "Decision_GWT.Decision"
53
+ ],
54
+ [
55
+ /\bBehavior_GWT\b/g,
56
+ "Decision_GWT"
57
+ ],
58
+ [
59
+ /\bReventless\.Behavior\b/g,
60
+ "Reventless.Decision"
61
+ ],
62
+ [
63
+ /\bStateChangeSlice\.Behavior\b/g,
64
+ "StateChangeSlice.Decision"
65
+ ],
66
+ [
67
+ /\bMapping_GWT\.FromBehavior\b/g,
68
+ "Mapping_GWT.FromDecision"
69
+ ],
70
+ [
71
+ /\bthenRefused\b/g,
72
+ "thenForbidden"
73
+ ],
74
+ [
75
+ /\b([A-Z][A-Za-z0-9]*)_Behavior\b/g,
76
+ "$1_Decision"
77
+ ]
78
+ ];
79
+
80
+ let localBinding = /^(\s*)module Behavior = /m;
81
+
82
+ function rewrite(source) {
83
+ let text = Stdlib_Array.reduce(replacements, source, (text, param) => text.replace(param[0], param[1]));
84
+ if (localBinding.test(text)) {
85
+ return text.replace(/^(\s*)module Behavior = /gm, "$1module Decision = ").replace(/\bBehavior\./g, "Decision.");
86
+ } else {
87
+ return text;
88
+ }
89
+ }
90
+
91
+ let skippedDirs = [
92
+ "node_modules",
93
+ "lib",
94
+ ".git"
95
+ ];
96
+
97
+ function isSource(name) {
98
+ if (name.endsWith(".res")) {
99
+ return true;
100
+ } else {
101
+ return name.endsWith(".resi");
102
+ }
103
+ }
104
+
105
+ let companions = [
106
+ ".res",
107
+ ".resi",
108
+ ".res.mjs",
109
+ ".res.js",
110
+ ".res.cjs"
111
+ ];
112
+
113
+ function walk(dir, files) {
114
+ Nodefs.readdirSync(dir, {
115
+ withFileTypes: true
116
+ }).forEach(entry => {
117
+ let name = entry.name;
118
+ let path = Nodepath.join(dir, name);
119
+ if (entry.isDirectory()) {
120
+ if (!skippedDirs.includes(name)) {
121
+ return walk(path, files);
122
+ } else {
123
+ return;
124
+ }
125
+ } else if (entry.isFile()) {
126
+ files.push(path);
127
+ return;
128
+ } else {
129
+ return;
130
+ }
131
+ });
132
+ }
133
+
134
+ let byPath = Primitive_string.compare;
135
+
136
+ function plan(dir) {
137
+ let files = [];
138
+ walk(dir, files);
139
+ files.sort(byPath);
140
+ let present = new Set(files);
141
+ let moves = files.filter(path => path.endsWith("_Behavior.res")).flatMap(source => {
142
+ let stem = source.slice(0, source.length - 13 | 0);
143
+ return Stdlib_Array.filterMap(companions, suffix => {
144
+ let from = stem + "_Behavior" + suffix;
145
+ if (present.has(from)) {
146
+ return {
147
+ from: from,
148
+ to_: stem + "_Decision" + suffix
149
+ };
150
+ }
151
+ });
152
+ });
153
+ let edits = Stdlib_Array.filterMap(files, path => {
154
+ if (!isSource(Nodepath.basename(path))) {
155
+ return;
156
+ }
157
+ let contents = Nodefs.readFileSync(path, "utf8");
158
+ let rewritten = rewrite(contents);
159
+ if (rewritten === contents) {
160
+ return;
161
+ } else {
162
+ return {
163
+ path: path,
164
+ contents: rewritten
165
+ };
166
+ }
167
+ });
168
+ let match = moves.find(param => present.has(param.to_));
169
+ if (match !== undefined) {
170
+ return {
171
+ TAG: "Error",
172
+ _0: match.to_ + ` already exists, so ` + match.from + ` cannot take its name. Nothing was changed.`
173
+ };
174
+ } else {
175
+ return {
176
+ TAG: "Ok",
177
+ _0: {
178
+ moves: moves,
179
+ edits: edits
180
+ }
181
+ };
182
+ }
183
+ }
184
+
185
+ function git(cwd, args) {
186
+ return Nodechild_process.spawnSync("git", args, {
187
+ cwd: cwd,
188
+ encoding: "utf8",
189
+ stdio: [
190
+ "ignore",
191
+ "pipe",
192
+ "pipe"
193
+ ]
194
+ });
195
+ }
196
+
197
+ function succeeded(result) {
198
+ return Primitive_object.equal(Primitive_option.fromNullable(result.status), 0);
199
+ }
200
+
201
+ function isTracked(path) {
202
+ return succeeded(git(Nodepath.dirname(path), [
203
+ "ls-files",
204
+ "--error-unmatch",
205
+ "--",
206
+ Nodepath.basename(path)
207
+ ]));
208
+ }
209
+
210
+ function moveFile(param) {
211
+ let to_ = param.to_;
212
+ let from = param.from;
213
+ if (isTracked(from)) {
214
+ let result = git(Nodepath.dirname(from), [
215
+ "mv",
216
+ "--",
217
+ Nodepath.basename(from),
218
+ Nodepath.basename(to_)
219
+ ]);
220
+ if (succeeded(result)) {
221
+ return {
222
+ TAG: "Ok",
223
+ _0: undefined
224
+ };
225
+ } else {
226
+ return {
227
+ TAG: "Error",
228
+ _0: `git mv ` + from + `: ` + Stdlib_Option.getOr(Primitive_option.fromNullable(result.stderr), "").trim()
229
+ };
230
+ }
231
+ }
232
+ try {
233
+ Nodefs.renameSync(from, to_);
234
+ return {
235
+ TAG: "Ok",
236
+ _0: undefined
237
+ };
238
+ } catch (raw_e) {
239
+ let e = Primitive_exceptions.internalToException(raw_e);
240
+ if (e.RE_EXN_ID === "JsExn") {
241
+ return {
242
+ TAG: "Error",
243
+ _0: `rename ` + from + `: ` + Stdlib_Option.getOr(Stdlib_JsExn.message(e._1), "failed")
244
+ };
245
+ }
246
+ throw e;
247
+ }
248
+ }
249
+
250
+ function apply(param) {
251
+ param.edits.forEach(param => {
252
+ Nodefs.writeFileSync(param.path, param.contents, "utf8");
253
+ });
254
+ return Stdlib_Array.reduce(param.moves, {
255
+ TAG: "Ok",
256
+ _0: undefined
257
+ }, (done, move) => Stdlib_Result.flatMap(done, () => moveFile(move)));
258
+ }
259
+
260
+ function describe(param, dryRun) {
261
+ let edits = param.edits;
262
+ let moves = param.moves;
263
+ let verb = dryRun ? "would " : "";
264
+ let lines = Belt_Array.concatMany([
265
+ moves.map(param => verb + `move ` + param.from + ` -> ` + param.to_),
266
+ edits.map(param => verb + `edit ` + param.path)
267
+ ]);
268
+ let movedSources = moves.filter(param => param.from.endsWith(".res")).length;
269
+ lines.push((
270
+ dryRun ? "Would rename" : "Renamed"
271
+ ) + ` ` + movedSources.toString() + ` file(s) and ` + (
272
+ dryRun ? "edit" : "edited"
273
+ ) + ` ` + edits.length.toString() + `.`);
274
+ return lines;
275
+ }
276
+
277
+ function execute(param) {
278
+ let dir = param.dir;
279
+ if (!Nodefs.existsSync(dir)) {
280
+ return {
281
+ TAG: "Error",
282
+ _0: dir + ` does not exist.`
283
+ };
284
+ }
285
+ let dryRun = param.dryRun;
286
+ return Stdlib_Result.flatMap(plan(dir), plan => {
287
+ if (dryRun) {
288
+ return {
289
+ TAG: "Ok",
290
+ _0: describe(plan, dryRun)
291
+ };
292
+ } else {
293
+ return Stdlib_Result.map(apply(plan), () => describe(plan, dryRun));
294
+ }
295
+ });
296
+ }
297
+
298
+ function main() {
299
+ return CliArgs$Reventless.run(cli, undefined, undefined, async args => {
300
+ let lines = execute(args);
301
+ if (lines.TAG === "Ok") {
302
+ lines._0.forEach(line => {
303
+ console.log(line);
304
+ });
305
+ return;
306
+ }
307
+ console.error(`reventless-rename-to-decision: ` + lines._0);
308
+ process.exit(1);
309
+ });
310
+ }
311
+
312
+ export {
313
+ usage,
314
+ parseArgs,
315
+ cli,
316
+ replacements,
317
+ localBinding,
318
+ rewrite,
319
+ skippedDirs,
320
+ isSource,
321
+ companions,
322
+ walk,
323
+ byPath,
324
+ plan,
325
+ git,
326
+ succeeded,
327
+ isTracked,
328
+ moveFile,
329
+ apply,
330
+ describe,
331
+ execute,
332
+ main,
333
+ }
334
+ /* node:fs Not a pure module */
@@ -2,7 +2,7 @@
2
2
  Module type for an aggregate's identity and schema specification.
3
3
 
4
4
  Every aggregate defines a `Spec` module satisfying this type. The `Spec` is
5
- used by `Platform.Aggregate.Make` and by `Behavior.T` to fix the aggregate's
5
+ used by `Platform.Aggregate.Make` and by `Decision.T` to fix the aggregate's
6
6
  command, event, and error types.
7
7
 
8
8
  @example
@@ -76,7 +76,7 @@ let fromStructure = (structure: Plugin.pluginStructure): t => {
76
76
  let capabilityKeys =
77
77
  needs->Array.map(d => d.capability)->Belt.Set.String.fromArray->Belt.Set.String.toArray
78
78
  let capabilities = capabilityKeys->Array.filterMap(key =>
79
- // An unrecognised capability is dropped rather than passed through: the
79
+ // An unrecognized capability is dropped rather than passed through: the
80
80
  // generator downstream renders a real `Platform.capability` arm, and a name
81
81
  // this build cannot map has no arm to render.
82
82
  CapabilityNeed.fromString(key)->Option.map(need => {
@@ -4,7 +4,7 @@
4
4
  // (`generator/Discovery`) and the external tooling that classifies files by
5
5
  // folder (`reventless-gwt`'s `ComponentMeta`) both derive from this, so the two
6
6
  // can't drift — previously the generator accepted plural/short folder names that
7
- // the gwt discovery silently didn't recognise.
7
+ // the gwt discovery silently didn't recognize.
8
8
 
9
9
  type t =
10
10
  | StateChangeSlice
@@ -99,7 +99,7 @@ let bodySuffixes = [
99
99
  "_Projections",
100
100
  "_Projection",
101
101
  "_Mappings",
102
- "_Behavior",
102
+ "_Decision",
103
103
  "_Automation",
104
104
  "_Translation",
105
105
  ]
@@ -112,7 +112,7 @@ let bodySuffixes = [
112
112
  "_Projections",
113
113
  "_Projection",
114
114
  "_Mappings",
115
- "_Behavior",
115
+ "_Decision",
116
116
  "_Automation",
117
117
  "_Translation"
118
118
  ];
@@ -46,10 +46,10 @@ The four rules (over the representation):
46
46
  and this module stays schema-agnostic by taking the name alone.
47
47
 
48
48
  `byTag` marks the exception: an identity the *name* does not declare, which an
49
- adapter recognised from an explicit `@partitionTag`. A domain's own identifier
49
+ adapter recognized from an explicit `@partitionTag`. A domain's own identifier
50
50
  is often not suffixed — `sku`, `isbn`, `vin` — and without this the annotation
51
51
  naming one would be extracted as a hint and then dropped, because `seedOf`
52
- only honours a hint already among the produced keys. So the escape hatch would
52
+ only honors a hint already among the produced keys. So the escape hatch would
53
53
  have worked for every field except the ones that need it.
54
54
 
55
55
  It is carried rather than folded in because removing the annotation removes
@@ -100,7 +100,7 @@ let dcbPartitionTagId: S.Metadata.Id.t<bool> = S.Metadata.Id.make(
100
100
  Internal sury metadata ID marking a tag field as *cross-partition* — readable
101
101
  across every partition that carries it (a secondary-tag read), not just the
102
102
  partition it is the partition key of. Opt-in; absence = the default
103
- partition-scoped behaviour. The scope is a property of the tag *key* and must
103
+ partition-scoped behavior. The scope is a property of the tag *key* and must
104
104
  agree across every event type that carries it (the fence-scope half depends on
105
105
  it). See `docs/analysis/dcb-consistency-check-issues.md` Issue 13.
106
106
  */
@@ -497,7 +497,7 @@ tag the catalog's own events write. A key derived from `lineItems` would name a
497
497
  tag no producer has ever written, and the decision read would come back empty —
498
498
  the identical symptom to extracting no tags at all, from a different cause. An
499
499
  author who wants another key still writes `DcbTag.stringForKey` on the nested
500
- field, which `resolveTagKey` honours here as it does at the top level.
500
+ field, which `resolveTagKey` honors here as it does at the top level.
501
501
  */
502
502
  let nestedRecordTags = (fieldSchema: S.t<unknown>, jsonValue: JSON.t): array<tag> =>
503
503
  switch nestedRecordProperties(fieldSchema) {
@@ -655,7 +655,7 @@ let extractVariantNames = (schema: S.t<'a>): array<string> => {
655
655
  // intentionally excluded here: DCB event-type lookups can't WHERE-clause
656
656
  // on bare-string events, so Plugin_Structure.consumedEventTypes and
657
657
  // related graph fields would otherwise claim cross-component edges the
658
- // runtime can't honour. Callers that need every constructor (e.g.
658
+ // runtime can't honor. Callers that need every constructor (e.g.
659
659
  // mapping-mode `acceptedTags` filters that match a JSON envelope's
660
660
  // `event` TAG against the Delegate's full constructor set) should call
661
661
  // [`extractAllVariantNames`] instead.
@@ -729,7 +729,7 @@ let isVariantPayloadBearing = (schema: S.t<'a>, name: string): bool => {
729
729
  Extracts tags from a flat JSON object, expanding array values into per-element tags.
730
730
 
731
731
  For scalar tagged fields, behaves identically to `extractTagsFromProperties`.
732
- For array tagged fields, produces one tag per element. Tag keys honour an optional
732
+ For array tagged fields, produces one tag per element. Tag keys honor an optional
733
733
  `DcbTag.stringForKey(~key=...)` override on the (inner) schema; otherwise the field
734
734
  name is used.
735
735
 
@@ -1123,7 +1123,7 @@ let idFieldsOfProperties = (properties: dict<S.t<unknown>>): array<DcbScopeInfer
1123
1123
  let isIdName = (name: string) => name->String.endsWith("Ids") || name->String.endsWith("Id")
1124
1124
  // An explicit `@partitionTag` declares an identity the naming convention cannot
1125
1125
  // express — a domain's own identifier is often unsuffixed (`sku`, `isbn`).
1126
- // Without this the hint is extracted and then ignored, since `seedOf` honours
1126
+ // Without this the hint is extracted and then ignored, since `seedOf` honors
1127
1127
  // only a hint already among the produced keys, so the escape hatch would work
1128
1128
  // for every field except the ones that need it. Flagged, not folded in: taking
1129
1129
  // the annotation away takes the identity with it, which is what the redundancy
@@ -76,14 +76,14 @@ module type Spec = {
76
76
  /**
77
77
  Event sources this slice subscribes to, by topic key.
78
78
 
79
- `[]` — the default and the historical behaviour — means this plugin's own DCB
79
+ `[]` — the default and the historical behavior — means this plugin's own DCB
80
80
  event log. Naming sources explicitly subscribes to them instead: an Aggregate's
81
81
  `Spec.name`, or a DCB source name (conventionally `"<pluginName>DcbEventLog"`),
82
82
  matching the keys `AutomationSlice` mappings already use.
83
83
 
84
84
  This exists because an outbound slice is the framework's one component for
85
85
  *calling an external service and feeding the answer back*, and that job is not
86
- specific to DCB-modelled entities. An Aggregate whose events should trigger an
86
+ specific to DCB-modeled entities. An Aggregate whose events should trigger an
87
87
  outbound call had no route to one while this list was hard-wired.
88
88
 
89
89
  Unlike `AutomationSlice`, the sources are a flat list rather than per-source
@@ -173,7 +173,7 @@ type commandDef = {
173
173
  means the command does not move the row. */
174
174
  targetState: option<string>,
175
175
  /** Where the from-set came from, ranking an inherited edge against an authored
176
- one the way `queryableDef.labelFieldSource` does for its field:
176
+ one the way `readSideDef.labelFieldSource` does for its field:
177
177
 
178
178
  - `"derived"` — the component's own scenarios.
179
179
  - `"declared"` — its `commandTransition` switch.
@@ -204,7 +204,7 @@ type commandDef = {
204
204
  }
205
205
 
206
206
  @schema
207
- type queryableDef = {
207
+ type readSideDef = {
208
208
  name: string,
209
209
  queryField: string,
210
210
  schema: string,
@@ -276,7 +276,7 @@ type errorDef = {
276
276
  }
277
277
 
278
278
  @schema
279
- type writableDef = {
279
+ type writeSideDef = {
280
280
  name: string,
281
281
  commands: array<commandDef>,
282
282
  producedEventTypes: array<string>,
@@ -289,7 +289,7 @@ type writableDef = {
289
289
  required list still lacks the key — both admin resolvers heal absent ones to
290
290
  `[]` on read, and a new one must be added there too. */
291
291
  errors: array<errorDef>,
292
- /** Chapter grouping band — see `queryableDef.chapter`. */
292
+ /** Chapter grouping band — see `readSideDef.chapter`. */
293
293
  chapter: option<string>,
294
294
  }
295
295
 
@@ -299,7 +299,7 @@ type automationSliceDef = {
299
299
  consumedEventTypes: array<string>,
300
300
  producedCommandTypes: array<string>,
301
301
  targetName: string,
302
- /** Chapter grouping band — see `queryableDef.chapter`. */
302
+ /** Chapter grouping band — see `readSideDef.chapter`. */
303
303
  chapter: option<string>,
304
304
  /** The declared `schedule`, as the JSON of `Schedule.timeSchema`; `None` for an
305
305
  automation started by events only, and in a structure from before the field. */
@@ -314,7 +314,7 @@ type outboundTranslationSliceDef = {
314
314
  targetName: option<string>,
315
315
  // Foreign system this slice publishes to — drives the external box (Event Graph).
316
316
  externalSystem: option<string>,
317
- /** Chapter grouping band — see `queryableDef.chapter`. */
317
+ /** Chapter grouping band — see `readSideDef.chapter`. */
318
318
  chapter: option<string>,
319
319
  /** The topics this slice subscribes to, as `Spec.sourceNames` declares them —
320
320
  an Aggregate's `Spec.name` or a DCB source name. `Some([])` is the declared
@@ -333,7 +333,7 @@ type inboundTranslationSliceDef = {
333
333
  targetName: string,
334
334
  // Foreign system this slice receives from — drives the external box (Event Graph).
335
335
  externalSystem: option<string>,
336
- /** Chapter grouping band — see `queryableDef.chapter`. */
336
+ /** Chapter grouping band — see `readSideDef.chapter`. */
337
337
  chapter: option<string>,
338
338
  /** The roles any of its commands' rules name; see `commandDef`. */
339
339
  requiredRoles?: array<string>,
@@ -393,7 +393,7 @@ type extensionDef = {
393
393
  An extension point owned by a plugin, from the producer side.
394
394
 
395
395
  `sourceEventTypes` are the `Delegate`'s events feeding the published protocol,
396
- plugin-qualified to match `writableDef.producedEventTypes`. `commandTypes` is the
396
+ plugin-qualified to match `writeSideDef.producedEventTypes`. `commandTypes` is the
397
397
  EP's inbound protocol — None (read as []) for a `command = unit` EP, which routes
398
398
  nothing. Definitions persisted before a field was added must be re-emitted.
399
399
  */
@@ -451,7 +451,7 @@ whole structure.
451
451
  while it walks the components, because it is the only party that knows which one
452
452
  carried the declaration. Nothing in this record is a string a developer typed.
453
453
 
454
- It records ORIGIN, not behaviour — a grafted file is the host's to edit
454
+ It records ORIGIN, not behavior — a grafted file is the host's to edit
455
455
  afterwards. What answers "does it still behave like the trait" is the trait's own
456
456
  conformance suite, which runs in the consumer's build and is not this field.
457
457
  */
@@ -474,10 +474,10 @@ is fabricated and warned about, so it is the one shape to avoid. Regression suit
474
474
  */
475
475
  @schema
476
476
  type pluginStructure = {
477
- readModels: array<queryableDef>,
478
- stateViewSlices: array<queryableDef>,
479
- stateChangeSlices: array<writableDef>,
480
- aggregates: array<writableDef>,
477
+ readModels: array<readSideDef>,
478
+ stateViewSlices: array<readSideDef>,
479
+ stateChangeSlices: array<writeSideDef>,
480
+ aggregates: array<writeSideDef>,
481
481
  automationSlices: array<automationSliceDef>,
482
482
  outboundTranslationSlices: array<outboundTranslationSliceDef>,
483
483
  inboundTranslationSlices: array<inboundTranslationSliceDef>,
@@ -499,7 +499,7 @@ type pluginStructure = {
499
499
  component. Absent → None, read as []. The only signal a graft leaves that
500
500
  survives into a deployed plugin — every other one (the dependency, the
501
501
  variant spread, the rules alias, the conformance binding) is source-side.
502
- A claim about origin, never about behaviour: see `Trait`. */
502
+ A claim about origin, never about behavior: see `Trait`. */
503
503
  traitDeclarations: option<array<traitDeclaration>>,
504
504
  }
505
505
 
@@ -106,7 +106,7 @@ let commandDefSchema = Sury.$schema(s => ({
106
106
  ownerField: s.m(Sury.$option(Sury.string))
107
107
  }));
108
108
 
109
- let queryableDefSchema = Sury.$schema(s => ({
109
+ let readSideDefSchema = Sury.$schema(s => ({
110
110
  name: s.m(Sury.string),
111
111
  queryField: s.m(Sury.string),
112
112
  schema: s.m(Sury.string),
@@ -141,7 +141,7 @@ let errorDefSchema = Sury.$schema(s => ({
141
141
  references: s.m(Sury.array(fieldReferenceSchema))
142
142
  }));
143
143
 
144
- let writableDefSchema = Sury.$schema(s => ({
144
+ let writeSideDefSchema = Sury.$schema(s => ({
145
145
  name: s.m(Sury.string),
146
146
  commands: s.m(Sury.array(commandDefSchema)),
147
147
  producedEventTypes: s.m(Sury.array(Sury.string)),
@@ -239,10 +239,10 @@ let traitDeclarationSchema = Sury.$schema(s => ({
239
239
  }));
240
240
 
241
241
  let pluginStructureSchema = Sury.$schema(s => ({
242
- readModels: s.m(Sury.array(queryableDefSchema)),
243
- stateViewSlices: s.m(Sury.array(queryableDefSchema)),
244
- stateChangeSlices: s.m(Sury.array(writableDefSchema)),
245
- aggregates: s.m(Sury.array(writableDefSchema)),
242
+ readModels: s.m(Sury.array(readSideDefSchema)),
243
+ stateViewSlices: s.m(Sury.array(readSideDefSchema)),
244
+ stateChangeSlices: s.m(Sury.array(writeSideDefSchema)),
245
+ aggregates: s.m(Sury.array(writeSideDefSchema)),
246
246
  automationSlices: s.m(Sury.array(automationSliceDefSchema)),
247
247
  outboundTranslationSlices: s.m(Sury.array(outboundTranslationSliceDefSchema)),
248
248
  inboundTranslationSlices: s.m(Sury.array(inboundTranslationSliceDefSchema)),
@@ -290,10 +290,10 @@ export {
290
290
  commandLevelSchema,
291
291
  fieldReferenceSchema,
292
292
  commandDefSchema,
293
- queryableDefSchema,
293
+ readSideDefSchema,
294
294
  eventDefSchema,
295
295
  errorDefSchema,
296
- writableDefSchema,
296
+ writeSideDefSchema,
297
297
  automationSliceDefSchema,
298
298
  outboundTranslationSliceDefSchema,
299
299
  inboundTranslationSliceDefSchema,
@@ -9,7 +9,7 @@ facts about one field.
9
9
  It is declared where the field is declared, and read by anything that composes
10
10
  text somebody will read. That is the whole reason it lives here rather than
11
11
  beside whichever consumer happens to need it first: a marking that exists in one
12
- consumer is a marking the rest of the system cannot honour, and the domain model
12
+ consumer is a marking the rest of the system cannot honor, and the domain model
13
13
  is the only place that knows which values are sensitive.
14
14
 
15
15
  ## Absent means "not stated", not "safe"
@@ -1,15 +1,15 @@
1
1
  // Per-aggregate persisted-snapshot configuration
2
2
  // (docs/plans/done/aggregate-snapshotting.md).
3
3
  //
4
- // Snapshotting is opt-in and lives on the Behavior module (where `state` is
5
- // defined): `Behavior.T.snapshot = None` (the default, auto-injected by
6
- // `@@reventless.behavior`) keeps full replay; `Some(config)` makes the
4
+ // Snapshotting is opt-in and lives on the Decision module (where `state` is
5
+ // defined): `Decision.T.snapshot = None` (the default, auto-injected by
6
+ // `@@reventless.decision`) keeps full replay; `Some(config)` makes the
7
7
  // aggregate write a keep-one snapshot every `interval` events and seed cold
8
8
  // replays from the latest one. Snapshots are a read optimization only — the
9
9
  // OCC append remains the sole consistency primitive, and a missing, corrupt,
10
10
  // or schema-drifted snapshot degrades to full replay.
11
11
  //
12
- // Enable via the file-level attribute on a behavior file:
12
+ // Enable via the file-level attribute on a decision file:
13
13
  //
14
14
  // @@reventless.snapshots(100)
15
15
  //
@@ -20,7 +20,7 @@
20
20
  type config<'state> = {
21
21
  /** Write a snapshot after every N appended events. Required — no default. */
22
22
  interval: int,
23
- /** Sury schema for the behavior's state — serializes the persisted snapshot
23
+ /** Sury schema for the decision's state — serializes the persisted snapshot
24
24
  and (hashed) gates staleness across state-shape changes. */
25
25
  stateSchema: S.t<'state>,
26
26
  }
@@ -161,7 +161,7 @@ type stateAnnotationSpec = {
161
161
  command's declared edge is written in terms of, a board draws its columns
162
162
  from and a state diagram renders. `Some(name)` when one such annotation
163
163
  exists; the PPX errors on duplicate `@lifecycle` annotations within the same
164
- record. Codegen consumes this to populate `queryableDef.lifecycleField`, and
164
+ record. Codegen consumes this to populate `readSideDef.lifecycleField`, and
165
165
  falls back to a field literally named `"lifecycle"` whose shape is an enum
166
166
  when this annotation is absent — so a record whose field can honestly be
167
167
  called `lifecycle` declares one without ceremony.