@auto-engineer/narrative 1.138.0 → 1.140.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-test.log +5 -5
  3. package/.turbo/turbo-type-check.log +1 -1
  4. package/CHANGELOG.md +41 -0
  5. package/dist/scripts/convert-flow-exec.js +2 -2
  6. package/dist/scripts/convert-flow-exec.js.map +1 -1
  7. package/dist/scripts/print-schema.js +5 -5
  8. package/dist/scripts/print-schema.js.map +1 -1
  9. package/dist/src/fluent-builder.d.ts +29 -29
  10. package/dist/src/fluent-builder.d.ts.map +1 -1
  11. package/dist/src/fluent-builder.js +81 -81
  12. package/dist/src/fluent-builder.js.map +1 -1
  13. package/dist/src/{getNarratives.d.ts → getScenes.d.ts} +6 -6
  14. package/dist/src/getScenes.d.ts.map +1 -0
  15. package/dist/src/{getNarratives.js → getScenes.js} +16 -16
  16. package/dist/src/getScenes.js.map +1 -0
  17. package/dist/src/id/addAutoIds.d.ts.map +1 -1
  18. package/dist/src/id/addAutoIds.js +22 -22
  19. package/dist/src/id/addAutoIds.js.map +1 -1
  20. package/dist/src/id/hasAllIds.d.ts.map +1 -1
  21. package/dist/src/id/hasAllIds.js +2 -2
  22. package/dist/src/id/hasAllIds.js.map +1 -1
  23. package/dist/src/index.d.ts +8 -8
  24. package/dist/src/index.d.ts.map +1 -1
  25. package/dist/src/index.js +4 -4
  26. package/dist/src/index.js.map +1 -1
  27. package/dist/src/loader/index.js +1 -1
  28. package/dist/src/loader/index.js.map +1 -1
  29. package/dist/src/loader/runtime-cjs.js +1 -1
  30. package/dist/src/loader/runtime-cjs.js.map +1 -1
  31. package/dist/src/narrative-context.d.ts +9 -9
  32. package/dist/src/narrative-context.d.ts.map +1 -1
  33. package/dist/src/narrative-context.js +47 -47
  34. package/dist/src/narrative-context.js.map +1 -1
  35. package/dist/src/narrative-registry.d.ts +6 -6
  36. package/dist/src/narrative-registry.d.ts.map +1 -1
  37. package/dist/src/narrative-registry.js +26 -26
  38. package/dist/src/narrative-registry.js.map +1 -1
  39. package/dist/src/narrative.d.ts +5 -5
  40. package/dist/src/narrative.d.ts.map +1 -1
  41. package/dist/src/narrative.js +26 -27
  42. package/dist/src/narrative.js.map +1 -1
  43. package/dist/src/parse-graphql-request.d.ts +1 -1
  44. package/dist/src/parse-graphql-request.d.ts.map +1 -1
  45. package/dist/src/parse-graphql-request.js +3 -3
  46. package/dist/src/parse-graphql-request.js.map +1 -1
  47. package/dist/src/samples/items.narrative.js +2 -2
  48. package/dist/src/samples/items.narrative.js.map +1 -1
  49. package/dist/src/samples/mixed-given-types.narrative.js +2 -2
  50. package/dist/src/samples/mixed-given-types.narrative.js.map +1 -1
  51. package/dist/src/samples/place-order.narrative.js +2 -2
  52. package/dist/src/samples/place-order.narrative.js.map +1 -1
  53. package/dist/src/samples/questionnaires.narrative.js +2 -2
  54. package/dist/src/samples/questionnaires.narrative.js.map +1 -1
  55. package/dist/src/samples/seasonal-assistant.schema.json +2 -2
  56. package/dist/src/samples/test-with-ids.narrative.js +2 -2
  57. package/dist/src/samples/test-with-ids.narrative.js.map +1 -1
  58. package/dist/src/schema.d.ts +136 -136
  59. package/dist/src/schema.d.ts.map +1 -1
  60. package/dist/src/schema.js +76 -76
  61. package/dist/src/schema.js.map +1 -1
  62. package/dist/src/slice-builder.d.ts +6 -6
  63. package/dist/src/slice-builder.d.ts.map +1 -1
  64. package/dist/src/slice-builder.js +21 -21
  65. package/dist/src/slice-builder.js.map +1 -1
  66. package/dist/src/transformers/model-to-narrative/analysis/lint-helpers.js +1 -1
  67. package/dist/src/transformers/model-to-narrative/analysis/lint-helpers.js.map +1 -1
  68. package/dist/src/transformers/model-to-narrative/cross-module-imports.js +4 -4
  69. package/dist/src/transformers/model-to-narrative/cross-module-imports.js.map +1 -1
  70. package/dist/src/transformers/model-to-narrative/generators/compose.js +3 -3
  71. package/dist/src/transformers/model-to-narrative/generators/compose.js.map +1 -1
  72. package/dist/src/transformers/model-to-narrative/generators/flow.d.ts +2 -2
  73. package/dist/src/transformers/model-to-narrative/generators/flow.d.ts.map +1 -1
  74. package/dist/src/transformers/model-to-narrative/generators/flow.js +20 -20
  75. package/dist/src/transformers/model-to-narrative/generators/flow.js.map +1 -1
  76. package/dist/src/transformers/model-to-narrative/generators/imports.d.ts +1 -1
  77. package/dist/src/transformers/model-to-narrative/generators/imports.d.ts.map +1 -1
  78. package/dist/src/transformers/model-to-narrative/generators/imports.js +1 -1
  79. package/dist/src/transformers/model-to-narrative/generators/imports.js.map +1 -1
  80. package/dist/src/transformers/model-to-narrative/generators/module-code.js +14 -14
  81. package/dist/src/transformers/model-to-narrative/generators/module-code.js.map +1 -1
  82. package/dist/src/transformers/model-to-narrative/index.d.ts +4 -4
  83. package/dist/src/transformers/model-to-narrative/index.d.ts.map +1 -1
  84. package/dist/src/transformers/model-to-narrative/index.js +1 -1
  85. package/dist/src/transformers/model-to-narrative/spec-traversal.d.ts +2 -2
  86. package/dist/src/transformers/model-to-narrative/spec-traversal.d.ts.map +1 -1
  87. package/dist/src/transformers/model-to-narrative/spec-traversal.js +5 -5
  88. package/dist/src/transformers/model-to-narrative/spec-traversal.js.map +1 -1
  89. package/dist/src/transformers/model-to-narrative/types.d.ts +1 -1
  90. package/dist/src/transformers/model-to-narrative/types.d.ts.map +1 -1
  91. package/dist/src/transformers/model-to-narrative/utils/integration-extractor.d.ts +1 -1
  92. package/dist/src/transformers/model-to-narrative/utils/integration-extractor.d.ts.map +1 -1
  93. package/dist/src/transformers/model-to-narrative/utils/integration-extractor.js +4 -4
  94. package/dist/src/transformers/model-to-narrative/utils/integration-extractor.js.map +1 -1
  95. package/dist/src/transformers/model-to-narrative/validate-modules.d.ts +1 -1
  96. package/dist/src/transformers/model-to-narrative/validate-modules.d.ts.map +1 -1
  97. package/dist/src/transformers/model-to-narrative/validate-modules.js +19 -19
  98. package/dist/src/transformers/model-to-narrative/validate-modules.js.map +1 -1
  99. package/dist/src/transformers/narrative-to-model/assemble.d.ts +2 -2
  100. package/dist/src/transformers/narrative-to-model/assemble.d.ts.map +1 -1
  101. package/dist/src/transformers/narrative-to-model/assemble.js +10 -3
  102. package/dist/src/transformers/narrative-to-model/assemble.js.map +1 -1
  103. package/dist/src/transformers/narrative-to-model/debug.d.ts.map +1 -1
  104. package/dist/src/transformers/narrative-to-model/debug.js +1 -1
  105. package/dist/src/transformers/narrative-to-model/debug.js.map +1 -1
  106. package/dist/src/transformers/narrative-to-model/derive-modules.d.ts +2 -2
  107. package/dist/src/transformers/narrative-to-model/derive-modules.d.ts.map +1 -1
  108. package/dist/src/transformers/narrative-to-model/derive-modules.js +9 -9
  109. package/dist/src/transformers/narrative-to-model/derive-modules.js.map +1 -1
  110. package/dist/src/transformers/narrative-to-model/index.d.ts +2 -2
  111. package/dist/src/transformers/narrative-to-model/index.d.ts.map +1 -1
  112. package/dist/src/transformers/narrative-to-model/index.js +39 -39
  113. package/dist/src/transformers/narrative-to-model/index.js.map +1 -1
  114. package/dist/src/transformers/narrative-to-model/spec-processors.js +1 -1
  115. package/dist/src/transformers/narrative-to-model/spec-processors.js.map +1 -1
  116. package/dist/src/transformers/narrative-to-model/strings.d.ts +1 -1
  117. package/dist/src/transformers/narrative-to-model/strings.d.ts.map +1 -1
  118. package/dist/src/transformers/narrative-to-model/strings.js +6 -6
  119. package/dist/src/transformers/narrative-to-model/strings.js.map +1 -1
  120. package/dist/src/validate-slice-requests.d.ts +4 -4
  121. package/dist/src/validate-slice-requests.d.ts.map +1 -1
  122. package/dist/src/validate-slice-requests.js +34 -34
  123. package/dist/src/validate-slice-requests.js.map +1 -1
  124. package/dist/tsconfig.tsbuildinfo +1 -1
  125. package/package.json +4 -4
  126. package/scripts/convert-flow-exec.ts +2 -2
  127. package/scripts/print-schema.ts +8 -8
  128. package/src/fluent-builder.specs.ts +3 -3
  129. package/src/fluent-builder.ts +141 -141
  130. package/src/{getNarratives.cache.specs.ts → getScenes.cache.specs.ts} +45 -45
  131. package/src/{getNarratives.specs.ts → getScenes.specs.ts} +302 -300
  132. package/src/{getNarratives.ts → getScenes.ts} +20 -20
  133. package/src/id/addAutoIds.specs.ts +105 -105
  134. package/src/id/addAutoIds.ts +26 -26
  135. package/src/id/hasAllIds.specs.ts +59 -59
  136. package/src/id/hasAllIds.ts +6 -6
  137. package/src/index.ts +12 -13
  138. package/src/loader/index.ts +1 -1
  139. package/src/loader/runtime-cjs.ts +1 -1
  140. package/src/model-to-narrative.specs.ts +133 -135
  141. package/src/narrative-context.specs.ts +24 -24
  142. package/src/narrative-context.ts +61 -61
  143. package/src/narrative-registry.ts +31 -31
  144. package/src/narrative.ts +31 -33
  145. package/src/parse-graphql-request.specs.ts +5 -5
  146. package/src/parse-graphql-request.ts +3 -3
  147. package/src/samples/items.narrative.ts +2 -2
  148. package/src/samples/mixed-given-types.narrative.ts +2 -2
  149. package/src/samples/place-order.narrative.ts +2 -2
  150. package/src/samples/questionnaires.narrative.ts +2 -2
  151. package/src/samples/seasonal-assistant.schema.json +2 -2
  152. package/src/samples/test-with-ids.narrative.ts +2 -2
  153. package/src/schema.specs.ts +99 -91
  154. package/src/schema.ts +89 -89
  155. package/src/slice-builder.ts +30 -30
  156. package/src/transformers/model-to-narrative/analysis/lint-helpers.ts +1 -1
  157. package/src/transformers/model-to-narrative/cross-module-imports.specs.ts +43 -43
  158. package/src/transformers/model-to-narrative/cross-module-imports.ts +4 -4
  159. package/src/transformers/model-to-narrative/generators/compose.ts +4 -4
  160. package/src/transformers/model-to-narrative/generators/flow.ts +36 -36
  161. package/src/transformers/model-to-narrative/generators/imports.ts +1 -1
  162. package/src/transformers/model-to-narrative/generators/module-code.ts +15 -15
  163. package/src/transformers/model-to-narrative/index.ts +4 -4
  164. package/src/transformers/model-to-narrative/modules.specs.ts +58 -58
  165. package/src/transformers/model-to-narrative/spec-traversal.specs.ts +43 -43
  166. package/src/transformers/model-to-narrative/spec-traversal.ts +6 -6
  167. package/src/transformers/model-to-narrative/types.ts +1 -1
  168. package/src/transformers/model-to-narrative/utils/integration-extractor.ts +5 -5
  169. package/src/transformers/model-to-narrative/validate-modules.ts +22 -22
  170. package/src/transformers/narrative-to-model/assemble.ts +12 -4
  171. package/src/transformers/narrative-to-model/debug.ts +1 -1
  172. package/src/transformers/narrative-to-model/derive-modules.specs.ts +35 -35
  173. package/src/transformers/narrative-to-model/derive-modules.ts +11 -11
  174. package/src/transformers/narrative-to-model/index.ts +47 -47
  175. package/src/transformers/narrative-to-model/spec-processors.ts +1 -1
  176. package/src/transformers/narrative-to-model/strings.ts +6 -6
  177. package/src/transformers/narrative-to-model/type-inference.specs.ts +11 -11
  178. package/src/validate-slice-requests.specs.ts +113 -113
  179. package/src/validate-slice-requests.ts +49 -49
  180. package/dist/src/getNarratives.d.ts.map +0 -1
  181. package/dist/src/getNarratives.js.map +0 -1
@@ -3,15 +3,15 @@ import { fileURLToPath } from 'node:url';
3
3
  import { InMemoryFileStore } from '@auto-engineer/file-store';
4
4
  import { NodeFileStore } from '@auto-engineer/file-store/node';
5
5
  import { beforeEach, describe, expect, it } from 'vitest';
6
- import { clearGetNarrativesCache, getNarratives } from './getNarratives';
7
- import { type Example, type Model, modelToNarrative, type Narrative, type QuerySlice } from './index';
6
+ import { clearGetScenesCache, getScenes } from './getScenes';
7
+ import { type Example, type Model, modelToNarrative, type QueryMoment, type Scene } from './index';
8
8
  import { modelSchema } from './schema';
9
9
 
10
10
  const __filename = fileURLToPath(import.meta.url);
11
11
  const __dirname = path.dirname(__filename);
12
12
  const pattern = /\.(narrative)\.(ts)$/;
13
13
 
14
- describe('getNarratives', (_mode) => {
14
+ describe('getScenes', (_mode) => {
15
15
  let vfs: NodeFileStore;
16
16
  let root: string;
17
17
 
@@ -19,8 +19,8 @@ describe('getNarratives', (_mode) => {
19
19
  vfs = new NodeFileStore();
20
20
  root = path.resolve(__dirname);
21
21
  });
22
- it('loads multiple narratives and generates correct models', async () => {
23
- const flows = await getNarratives({ vfs, root: path.resolve(__dirname), pattern, fastFsScan: true });
22
+ it('loads multiple scenes and generates correct models', async () => {
23
+ const flows = await getScenes({ vfs, root: path.resolve(__dirname), pattern, fastFsScan: true });
24
24
  const schemas = flows.toModel();
25
25
 
26
26
  const parseResult = modelSchema.safeParse(schemas);
@@ -30,11 +30,11 @@ describe('getNarratives', (_mode) => {
30
30
  expect(parseResult.success).toBe(true);
31
31
 
32
32
  expect(schemas).toHaveProperty('variant', 'specs');
33
- expect(schemas).toHaveProperty('narratives');
33
+ expect(schemas).toHaveProperty('scenes');
34
34
  expect(schemas).toHaveProperty('messages');
35
35
  expect(schemas).toHaveProperty('integrations');
36
36
 
37
- const flowsArray = schemas.narratives;
37
+ const flowsArray = schemas.scenes;
38
38
  expect(Array.isArray(flowsArray)).toBe(true);
39
39
  expect(flowsArray.length).toBeGreaterThanOrEqual(2);
40
40
 
@@ -48,24 +48,24 @@ describe('getNarratives', (_mode) => {
48
48
  expect(placeOrder).toBeDefined();
49
49
 
50
50
  if (items) {
51
- expect(items.slices).toHaveLength(2);
52
- const createItemSlice = items.slices[0];
53
- expect(createItemSlice.type).toBe('command');
54
- expect(createItemSlice.name).toBe('Create item');
55
- expect(createItemSlice.stream).toBe('item-${id}');
56
- if (createItemSlice.type === 'command') {
57
- expect(createItemSlice.client.specs).toBeDefined();
58
- expect(Array.isArray(createItemSlice.client.specs)).toBe(true);
59
- expect(createItemSlice.client.specs).toHaveLength(1);
60
- expect(createItemSlice.client.specs[0].type).toBe('describe');
61
- expect(createItemSlice.client.specs[0].title).toBe('A form that allows users to add items');
62
- if (createItemSlice.client.specs[0].type === 'describe') {
63
- expect(createItemSlice.client.specs[0].children).toHaveLength(1);
51
+ expect(items.moments).toHaveLength(2);
52
+ const createItemMoment = items.moments[0];
53
+ expect(createItemMoment.type).toBe('command');
54
+ expect(createItemMoment.name).toBe('Create item');
55
+ expect(createItemMoment.stream).toBe('item-${id}');
56
+ if (createItemMoment.type === 'command') {
57
+ expect(createItemMoment.client.specs).toBeDefined();
58
+ expect(Array.isArray(createItemMoment.client.specs)).toBe(true);
59
+ expect(createItemMoment.client.specs).toHaveLength(1);
60
+ expect(createItemMoment.client.specs[0].type).toBe('describe');
61
+ expect(createItemMoment.client.specs[0].title).toBe('A form that allows users to add items');
62
+ if (createItemMoment.client.specs[0].type === 'describe') {
63
+ expect(createItemMoment.client.specs[0].children).toHaveLength(1);
64
64
  }
65
- expect(createItemSlice.server.specs).toBeDefined();
66
- expect(Array.isArray(createItemSlice.server.specs)).toBe(true);
67
- expect(createItemSlice.server.specs).toHaveLength(1);
68
- const spec = createItemSlice.server.specs[0];
65
+ expect(createItemMoment.server.specs).toBeDefined();
66
+ expect(Array.isArray(createItemMoment.server.specs)).toBe(true);
67
+ expect(createItemMoment.server.specs).toHaveLength(1);
68
+ const spec = createItemMoment.server.specs[0];
69
69
  expect(spec.feature).toBeDefined();
70
70
  expect(spec.rules).toHaveLength(1);
71
71
  const rule = spec.rules[0];
@@ -95,55 +95,55 @@ describe('getNarratives', (_mode) => {
95
95
  }
96
96
  }
97
97
 
98
- const viewItemSlice = items.slices[1] as QuerySlice;
99
- expect(viewItemSlice.type).toBe('query');
100
- expect(viewItemSlice.name).toBe('view items');
101
- expect(viewItemSlice.client.specs).toBeDefined();
102
- expect(Array.isArray(viewItemSlice.client.specs)).toBe(true);
103
- expect(viewItemSlice.client.specs).toHaveLength(1);
104
- expect(viewItemSlice.client.specs[0].type).toBe('describe');
105
- expect(viewItemSlice.client.specs[0].title).toBe('view Items Screen');
106
- if (viewItemSlice.client.specs[0].type === 'describe') {
107
- expect(viewItemSlice.client.specs[0].children).toHaveLength(3);
98
+ const viewItemMoment = items.moments[1] as QueryMoment;
99
+ expect(viewItemMoment.type).toBe('query');
100
+ expect(viewItemMoment.name).toBe('view items');
101
+ expect(viewItemMoment.client.specs).toBeDefined();
102
+ expect(Array.isArray(viewItemMoment.client.specs)).toBe(true);
103
+ expect(viewItemMoment.client.specs).toHaveLength(1);
104
+ expect(viewItemMoment.client.specs[0].type).toBe('describe');
105
+ expect(viewItemMoment.client.specs[0].title).toBe('view Items Screen');
106
+ if (viewItemMoment.client.specs[0].type === 'describe') {
107
+ expect(viewItemMoment.client.specs[0].children).toHaveLength(3);
108
108
  }
109
- expect(viewItemSlice.request).toBeDefined();
110
- expect(viewItemSlice.request).toMatch(
109
+ expect(viewItemMoment.request).toBeDefined();
110
+ expect(viewItemMoment.request).toMatch(
111
111
  /query items\(\$itemId: String!\) {\s+items\(itemId: \$itemId\) {\s+id\s+description\s+}/,
112
112
  );
113
113
 
114
- const data = viewItemSlice?.server?.data;
114
+ const data = viewItemMoment?.server?.data;
115
115
  if (!data || !Array.isArray(data.items)) throw new Error('No data found in view items slice');
116
116
 
117
117
  expect(data.items).toHaveLength(1);
118
118
  expect(data.items[0].target).toMatchObject({ type: 'State', name: 'items' });
119
119
  expect(data.items[0].origin).toMatchObject({ name: 'ItemsProjection', type: 'projection' });
120
120
 
121
- const specs = viewItemSlice?.server?.specs;
121
+ const specs = viewItemMoment?.server?.specs;
122
122
  if (specs == null || specs.length === 0 || specs[0].feature === '')
123
123
  throw new Error('No specs found in view items slice');
124
124
  expect(specs).toBeDefined();
125
125
  }
126
126
 
127
127
  if (placeOrder) {
128
- expect(placeOrder.slices).toHaveLength(1);
129
- const submitOrderSlice = placeOrder.slices[0];
130
- expect(submitOrderSlice.type).toBe('command');
131
- expect(submitOrderSlice.name).toBe('Submit order');
132
- expect(submitOrderSlice.stream).toBe('order-${orderId}');
133
-
134
- if (submitOrderSlice.type === 'command') {
135
- expect(submitOrderSlice.client.specs).toBeDefined();
136
- expect(Array.isArray(submitOrderSlice.client.specs)).toBe(true);
137
- expect(submitOrderSlice.client.specs).toHaveLength(1);
138
- expect(submitOrderSlice.client.specs[0].type).toBe('describe');
139
- expect(submitOrderSlice.client.specs[0].title).toBe('Order submission form');
140
- if (submitOrderSlice.client.specs[0].type === 'describe') {
141
- expect(submitOrderSlice.client.specs[0].children).toHaveLength(2);
128
+ expect(placeOrder.moments).toHaveLength(1);
129
+ const submitOrderMoment = placeOrder.moments[0];
130
+ expect(submitOrderMoment.type).toBe('command');
131
+ expect(submitOrderMoment.name).toBe('Submit order');
132
+ expect(submitOrderMoment.stream).toBe('order-${orderId}');
133
+
134
+ if (submitOrderMoment.type === 'command') {
135
+ expect(submitOrderMoment.client.specs).toBeDefined();
136
+ expect(Array.isArray(submitOrderMoment.client.specs)).toBe(true);
137
+ expect(submitOrderMoment.client.specs).toHaveLength(1);
138
+ expect(submitOrderMoment.client.specs[0].type).toBe('describe');
139
+ expect(submitOrderMoment.client.specs[0].title).toBe('Order submission form');
140
+ if (submitOrderMoment.client.specs[0].type === 'describe') {
141
+ expect(submitOrderMoment.client.specs[0].children).toHaveLength(2);
142
142
  }
143
- expect(submitOrderSlice.server.specs).toBeDefined();
144
- expect(Array.isArray(submitOrderSlice.server.specs)).toBe(true);
145
- expect(submitOrderSlice.server.specs).toHaveLength(1);
146
- const spec = submitOrderSlice.server.specs[0];
143
+ expect(submitOrderMoment.server.specs).toBeDefined();
144
+ expect(Array.isArray(submitOrderMoment.server.specs)).toBe(true);
145
+ expect(submitOrderMoment.server.specs).toHaveLength(1);
146
+ const spec = submitOrderMoment.server.specs[0];
147
147
  expect(spec.rules).toHaveLength(1);
148
148
  const rule = spec.rules[0];
149
149
  expect(rule.examples).toHaveLength(1);
@@ -206,21 +206,21 @@ describe('getNarratives', (_mode) => {
206
206
  });
207
207
 
208
208
  it('validates the complete schema with Zod', async () => {
209
- const flows = await getNarratives({ vfs: vfs, root, pattern: /\.(narrative)\.(ts)$/, fastFsScan: true });
209
+ const flows = await getScenes({ vfs: vfs, root, pattern: /\.(narrative)\.(ts)$/, fastFsScan: true });
210
210
  const schemas = flows.toModel();
211
211
  const parsed = modelSchema.parse(schemas);
212
212
  expect(parsed.variant).toBe('specs');
213
- expect(Array.isArray(parsed.narratives)).toBe(true);
213
+ expect(Array.isArray(parsed.scenes)).toBe(true);
214
214
  expect(Array.isArray(parsed.messages)).toBe(true);
215
215
  expect(Array.isArray(parsed.integrations)).toBe(true);
216
216
  });
217
217
 
218
- it('should handle narratives with integrations', async () => {
219
- const flows = await getNarratives({ vfs: vfs, root: root, pattern: /\.(narrative)\.(ts)$/, fastFsScan: true });
218
+ it('should handle scenes with integrations', async () => {
219
+ const flows = await getScenes({ vfs: vfs, root: root, pattern: /\.(narrative)\.(ts)$/, fastFsScan: true });
220
220
  const specsSchema = flows.toModel();
221
221
 
222
- const flowsWithIntegrations = specsSchema.narratives.filter((f) =>
223
- f.slices.some((s) => {
222
+ const flowsWithIntegrations = specsSchema.scenes.filter((f) =>
223
+ f.moments.some((s) => {
224
224
  if (s.type === 'command' || s.type === 'query') {
225
225
  return (
226
226
  s.server.data?.items?.some(
@@ -240,11 +240,11 @@ describe('getNarratives', (_mode) => {
240
240
  });
241
241
 
242
242
  it('should handle react slices correctly', async () => {
243
- const flows = await getNarratives({ vfs: vfs, root: root, pattern: /\.(narrative)\.(ts)$/, fastFsScan: true });
243
+ const flows = await getScenes({ vfs: vfs, root: root, pattern: /\.(narrative)\.(ts)$/, fastFsScan: true });
244
244
  const specsSchema = flows.toModel();
245
245
 
246
- const reactSlices = specsSchema.narratives.flatMap((f) => f.slices.filter((s) => s.type === 'react'));
247
- reactSlices.forEach((slice) => {
246
+ const reactMoments = specsSchema.scenes.flatMap((f) => f.moments.filter((s) => s.type === 'react'));
247
+ reactMoments.forEach((slice) => {
248
248
  if (slice.type === 'react') {
249
249
  expect(slice.server).toBeDefined();
250
250
  expect(slice.server.specs).toBeDefined();
@@ -264,7 +264,7 @@ describe('getNarratives', (_mode) => {
264
264
  });
265
265
 
266
266
  it('should parse and validate a complete flow with all slice types', async () => {
267
- const flows = await getNarratives({ vfs: vfs, root: root, pattern: /\.(narrative)\.(ts)$/, fastFsScan: true });
267
+ const flows = await getScenes({ vfs: vfs, root: root, pattern: /\.(narrative)\.(ts)$/, fastFsScan: true });
268
268
  const schemas = flows.toModel();
269
269
 
270
270
  const validationResult = modelSchema.safeParse(schemas);
@@ -275,8 +275,8 @@ describe('getNarratives', (_mode) => {
275
275
 
276
276
  const validatedData = validationResult.data!;
277
277
  expect(
278
- validatedData.narratives.every((flow) =>
279
- flow.slices.every((slice) => {
278
+ validatedData.scenes.every((flow) =>
279
+ flow.moments.every((slice) => {
280
280
  if (slice.type === 'command' || slice.type === 'query') {
281
281
  return slice.client !== undefined && slice.server !== undefined;
282
282
  } else if (slice.type === 'react') {
@@ -290,94 +290,96 @@ describe('getNarratives', (_mode) => {
290
290
  ).toBe(true);
291
291
  });
292
292
 
293
- it('should have ids for narratives and slices that have ids', async () => {
294
- const flows = await getNarratives({ vfs: vfs, root: root, pattern: /\.(narrative)\.(ts)$/, fastFsScan: true });
293
+ it('should have ids for scenes and slices that have ids', async () => {
294
+ const flows = await getScenes({ vfs: vfs, root: root, pattern: /\.(narrative)\.(ts)$/, fastFsScan: true });
295
295
 
296
296
  const schemas = flows.toModel();
297
297
 
298
- const testFlowWithIds = schemas.narratives.find((f) => f.name === 'Test Flow with IDs');
298
+ const testFlowWithIds = schemas.scenes.find((f) => f.name === 'Test Flow with IDs');
299
299
  if (!testFlowWithIds) return;
300
- const commandSlice = testFlowWithIds.slices.find((s) => s.name === 'Create test item');
301
- expect(commandSlice?.id).toBe('SLICE-001');
302
- expect(commandSlice?.type).toBe('command');
303
- const querySlice = testFlowWithIds.slices.find((s) => s.name === 'Get test items');
304
- expect(querySlice?.id).toBe('SLICE-002');
305
- expect(querySlice?.type).toBe('query');
306
- const reactSlice = testFlowWithIds.slices.find((s) => s.name === 'React to test event');
307
- expect(reactSlice?.id).toBe('SLICE-003');
308
- expect(reactSlice?.type).toBe('react');
300
+ const commandMoment = testFlowWithIds.moments.find((s) => s.name === 'Create test item');
301
+ expect(commandMoment?.id).toBe('SLICE-001');
302
+ expect(commandMoment?.type).toBe('command');
303
+ const queryMoment = testFlowWithIds.moments.find((s) => s.name === 'Get test items');
304
+ expect(queryMoment?.id).toBe('SLICE-002');
305
+ expect(queryMoment?.type).toBe('query');
306
+ const reactMoment = testFlowWithIds.moments.find((s) => s.name === 'React to test event');
307
+ expect(reactMoment?.id).toBe('SLICE-003');
308
+ expect(reactMoment?.type).toBe('react');
309
309
  });
310
310
 
311
311
  it('should have ids for command slice rules', async () => {
312
- const flows = await getNarratives({ vfs: vfs, root: root, pattern: /\.(narrative)\.(ts)$/, fastFsScan: true });
312
+ const flows = await getScenes({ vfs: vfs, root: root, pattern: /\.(narrative)\.(ts)$/, fastFsScan: true });
313
313
  const schemas = flows.toModel();
314
314
 
315
- const testFlowWithIds = schemas.narratives.find((f) => f.name === 'Test Flow with IDs');
315
+ const testFlowWithIds = schemas.scenes.find((f) => f.name === 'Test Flow with IDs');
316
316
  if (!testFlowWithIds) return;
317
317
 
318
- const commandSlice = testFlowWithIds.slices.find((s) => s.name === 'Create test item');
319
- if (commandSlice?.type !== 'command') return;
318
+ const commandMoment = testFlowWithIds.moments.find((s) => s.name === 'Create test item');
319
+ if (commandMoment?.type !== 'command') return;
320
320
 
321
- expect(commandSlice.server.specs[0].rules).toHaveLength(2);
321
+ expect(commandMoment.server.specs[0].rules).toHaveLength(2);
322
322
 
323
- const rule1 = commandSlice.server.specs[0].rules.find(
323
+ const rule1 = commandMoment.server.specs[0].rules.find(
324
324
  (r) => r.name === 'Valid test items should be created successfully',
325
325
  );
326
326
  expect(rule1?.id).toBe('RULE-001');
327
327
 
328
- const rule2 = commandSlice.server.specs[0].rules.find((r) => r.name === 'Invalid test items should be rejected');
328
+ const rule2 = commandMoment.server.specs[0].rules.find((r) => r.name === 'Invalid test items should be rejected');
329
329
  expect(rule2?.id).toBe('RULE-002');
330
330
  });
331
331
 
332
332
  it('should have ids for query slice rules', async () => {
333
- const flows = await getNarratives({ vfs: vfs, root: root, pattern: /\.(narrative)\.(ts)$/, fastFsScan: true });
333
+ const flows = await getScenes({ vfs: vfs, root: root, pattern: /\.(narrative)\.(ts)$/, fastFsScan: true });
334
334
  const schemas = flows.toModel();
335
335
 
336
- const testFlowWithIds = schemas.narratives.find((f) => f.name === 'Test Flow with IDs');
336
+ const testFlowWithIds = schemas.scenes.find((f) => f.name === 'Test Flow with IDs');
337
337
  if (!testFlowWithIds) return;
338
338
 
339
- const querySlice = testFlowWithIds.slices.find((s) => s.name === 'Get test items');
340
- if (querySlice?.type !== 'query') return;
339
+ const queryMoment = testFlowWithIds.moments.find((s) => s.name === 'Get test items');
340
+ if (queryMoment?.type !== 'query') return;
341
341
 
342
- expect(querySlice.server.specs[0].rules).toHaveLength(1);
342
+ expect(queryMoment.server.specs[0].rules).toHaveLength(1);
343
343
 
344
- const rule3 = querySlice.server.specs[0].rules.find((r) => r.name === 'Items should be retrievable after creation');
344
+ const rule3 = queryMoment.server.specs[0].rules.find(
345
+ (r) => r.name === 'Items should be retrievable after creation',
346
+ );
345
347
  expect(rule3?.id).toBe('RULE-003');
346
348
  });
347
349
 
348
350
  it('should have ids for react slice rules', async () => {
349
- const flows = await getNarratives({ vfs: vfs, root: root, pattern: /\.(narrative)\.(ts)$/, fastFsScan: true });
351
+ const flows = await getScenes({ vfs: vfs, root: root, pattern: /\.(narrative)\.(ts)$/, fastFsScan: true });
350
352
  const schemas = flows.toModel();
351
353
 
352
- const testFlowWithIds = schemas.narratives.find((f) => f.name === 'Test Flow with IDs');
354
+ const testFlowWithIds = schemas.scenes.find((f) => f.name === 'Test Flow with IDs');
353
355
  if (!testFlowWithIds) return;
354
356
 
355
- const reactSlice = testFlowWithIds.slices.find((s) => s.name === 'React to test event');
356
- if (reactSlice?.type !== 'react') return;
357
+ const reactMoment = testFlowWithIds.moments.find((s) => s.name === 'React to test event');
358
+ if (reactMoment?.type !== 'react') return;
357
359
 
358
- expect(reactSlice.server.specs[0].rules).toHaveLength(1);
360
+ expect(reactMoment.server.specs[0].rules).toHaveLength(1);
359
361
 
360
- const rule4 = reactSlice.server.specs[0].rules.find((r) => r.name === 'System should react to test item creation');
362
+ const rule4 = reactMoment.server.specs[0].rules.find((r) => r.name === 'System should react to test item creation');
361
363
  expect(rule4?.id).toBe('RULE-004');
362
364
  });
363
365
 
364
366
  it('should handle when examples correctly', async () => {
365
- const flows = await getNarratives({
367
+ const flows = await getScenes({
366
368
  vfs,
367
369
  root,
368
370
  pattern: /(?:^|\/)questionnaires\.narrative\.(?:ts|tsx|js|jsx|mjs|cjs)$/,
369
371
  });
370
372
  const model = flows.toModel();
371
373
 
372
- const questionnaireFlow = model.narratives.find((f) => f.name === 'Questionnaires');
374
+ const questionnaireFlow = model.scenes.find((f) => f.name === 'Questionnaires');
373
375
  expect(questionnaireFlow).toBeDefined();
374
376
 
375
377
  if (questionnaireFlow) {
376
- const submitSlice = questionnaireFlow.slices.find((s) => s.name === 'submits the questionnaire');
377
- expect(submitSlice?.type).toBe('command');
378
+ const submitMoment = questionnaireFlow.moments.find((s) => s.name === 'submits the questionnaire');
379
+ expect(submitMoment?.type).toBe('command');
378
380
 
379
- if (submitSlice?.type === 'command') {
380
- const example = submitSlice.server?.specs?.[0]?.rules[0]?.examples[0];
381
+ if (submitMoment?.type === 'command') {
382
+ const example = submitMoment.server?.specs?.[0]?.rules[0]?.examples[0];
381
383
  const whenStep = example?.steps?.find((s) => s.keyword === 'When');
382
384
  if (whenStep && 'text' in whenStep) {
383
385
  expect(whenStep.text).toBe('SubmitQuestionnaire');
@@ -387,7 +389,7 @@ describe('getNarratives', (_mode) => {
387
389
  });
388
390
 
389
391
  it('should correctly assign commandRef correctly', async () => {
390
- const flows = await getNarratives({
392
+ const flows = await getScenes({
391
393
  vfs,
392
394
  root,
393
395
  pattern: /(?:^|\/)questionnaires\.narrative\.(?:ts|tsx|js|jsx|mjs|cjs)$/,
@@ -400,9 +402,9 @@ describe('getNarratives', (_mode) => {
400
402
  it('should handle experience slice with client specs', async () => {
401
403
  const memoryVfs = new InMemoryFileStore();
402
404
  const flowWithExperienceContent = `
403
- import { flow, experience, it, specs } from '@auto-engineer/narrative';
405
+ import { scene, experience, it, specs } from '@auto-engineer/narrative';
404
406
 
405
- flow('Test Experience Flow', () => {
407
+ scene('Test Experience Flow', () => {
406
408
  experience('Homepage', 'H1a4Bn6Cy').client(() => {
407
409
  specs(() => {
408
410
  it('show a hero section with a welcome message');
@@ -414,26 +416,26 @@ flow('Test Experience Flow', () => {
414
416
 
415
417
  await memoryVfs.write('/test/experience.narrative.ts', new TextEncoder().encode(flowWithExperienceContent));
416
418
 
417
- const flows = await getNarratives({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
419
+ const flows = await getScenes({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
418
420
  const model = flows.toModel();
419
421
 
420
- const experienceFlow = model.narratives.find((f) => f.name === 'Test Experience Flow');
422
+ const experienceFlow = model.scenes.find((f) => f.name === 'Test Experience Flow');
421
423
  expect(experienceFlow).toBeDefined();
422
424
 
423
425
  if (experienceFlow) {
424
- const homepageSlice = experienceFlow.slices.find((s) => s.name === 'Homepage');
425
- expect(homepageSlice).toBeDefined();
426
- expect(homepageSlice?.type).toBe('experience');
427
-
428
- if (homepageSlice?.type === 'experience') {
429
- expect(homepageSlice.client).toBeDefined();
430
- expect(homepageSlice.client.specs).toBeDefined();
431
- expect(Array.isArray(homepageSlice.client.specs)).toBe(true);
432
- expect(homepageSlice.client.specs).toHaveLength(2);
433
- expect(homepageSlice.client.specs[0].type).toBe('it');
434
- expect(homepageSlice.client.specs[0].title).toBe('show a hero section with a welcome message');
435
- expect(homepageSlice.client.specs[1].type).toBe('it');
436
- expect(homepageSlice.client.specs[1].title).toBe('allow user to start the questionnaire');
426
+ const homepageMoment = experienceFlow.moments.find((s) => s.name === 'Homepage');
427
+ expect(homepageMoment).toBeDefined();
428
+ expect(homepageMoment?.type).toBe('experience');
429
+
430
+ if (homepageMoment?.type === 'experience') {
431
+ expect(homepageMoment.client).toBeDefined();
432
+ expect(homepageMoment.client.specs).toBeDefined();
433
+ expect(Array.isArray(homepageMoment.client.specs)).toBe(true);
434
+ expect(homepageMoment.client.specs).toHaveLength(2);
435
+ expect(homepageMoment.client.specs[0].type).toBe('it');
436
+ expect(homepageMoment.client.specs[0].title).toBe('show a hero section with a welcome message');
437
+ expect(homepageMoment.client.specs[1].type).toBe('it');
438
+ expect(homepageMoment.client.specs[1].title).toBe('allow user to start the questionnaire');
437
439
  }
438
440
  }
439
441
  });
@@ -441,9 +443,9 @@ flow('Test Experience Flow', () => {
441
443
  it('simulates browser execution with transpiled CommonJS code', async () => {
442
444
  const memoryVfs = new InMemoryFileStore();
443
445
  const flowContent = `
444
- import { flow, experience, it, specs } from '@auto-engineer/narrative';
446
+ import { scene, experience, it, specs } from '@auto-engineer/narrative';
445
447
 
446
- flow('Browser Test Flow', () => {
448
+ scene('Browser Test Flow', () => {
447
449
  experience('HomePage').client(() => {
448
450
  specs(() => {
449
451
  it('render correctly');
@@ -461,12 +463,12 @@ flow('Browser Test Flow', () => {
461
463
 
462
464
  await executeAST(['/browser/test.narrative.ts'], memoryVfs, {}, '/browser');
463
465
 
464
- const flows = registry.getAllNarratives();
466
+ const flows = registry.getAllScenes();
465
467
  expect(flows).toHaveLength(1);
466
468
  expect(flows[0].name).toBe('Browser Test Flow');
467
- expect(flows[0].slices).toHaveLength(1);
469
+ expect(flows[0].moments).toHaveLength(1);
468
470
 
469
- const slice = flows[0].slices[0];
471
+ const slice = flows[0].moments[0];
470
472
  expect(slice.type).toBe('experience');
471
473
  expect(slice.name).toBe('HomePage');
472
474
 
@@ -487,9 +489,9 @@ flow('Browser Test Flow', () => {
487
489
  const { registry } = await import('./narrative-registry');
488
490
 
489
491
  const flowContent = `
490
- import { flow, experience } from '@auto-engineer/narrative';
492
+ import { scene, experience } from '@auto-engineer/narrative';
491
493
 
492
- flow('Questionnaires', 'Q9m2Kp4Lx', () => {
494
+ scene('Questionnaires', 'Q9m2Kp4Lx', () => {
493
495
  experience('Homepage', 'H1a4Bn6Cy').client(() => {});
494
496
  });
495
497
  `;
@@ -502,12 +504,12 @@ flow('Questionnaires', 'Q9m2Kp4Lx', () => {
502
504
  executeAST(['/browser/questionnaires.narrative.ts'], memoryVfs, {}, '/browser'),
503
505
  ).resolves.toBeDefined();
504
506
 
505
- const flows = registry.getAllNarratives();
507
+ const flows = registry.getAllScenes();
506
508
  expect(flows).toHaveLength(1);
507
509
  expect(flows[0].name).toBe('Questionnaires');
508
- expect(flows[0].slices).toHaveLength(1);
510
+ expect(flows[0].moments).toHaveLength(1);
509
511
 
510
- const slice = flows[0].slices[0];
512
+ const slice = flows[0].moments[0];
511
513
  expect(slice.type).toBe('experience');
512
514
  expect(slice.name).toBe('Homepage');
513
515
  });
@@ -515,7 +517,7 @@ flow('Questionnaires', 'Q9m2Kp4Lx', () => {
515
517
  it('should handle flow type resolutions correctly', async () => {
516
518
  const memoryVfs = new InMemoryFileStore();
517
519
  const questionnaireFlowContent = `
518
- import { data, flow, should, specs, rule, example } from '../narrative';
520
+ import { data, scene, should, specs, rule, example } from '../narrative';
519
521
  import { command, query } from '../fluent-builder';
520
522
  import gql from 'graphql-tag';
521
523
  import { source } from '../data-narrative-builders';
@@ -562,7 +564,7 @@ type QuestionnaireProgress = State<
562
564
  }
563
565
  >;
564
566
 
565
- flow('questionnaires-test', () => {
567
+ scene('questionnaires-test', () => {
566
568
  query('views progress')
567
569
  .server(() => {
568
570
  specs('Questionnaire progress display', () => {
@@ -612,9 +614,9 @@ flow('questionnaires-test', () => {
612
614
 
613
615
  await memoryVfs.write('/test/questionnaires.narrative.ts', new TextEncoder().encode(questionnaireFlowContent));
614
616
 
615
- const flows = await getNarratives({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
617
+ const flows = await getScenes({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
616
618
  const model = flows.toModel();
617
- const testFlow = model.narratives.find((f) => f.name === 'questionnaires-test');
619
+ const testFlow = model.scenes.find((f) => f.name === 'questionnaires-test');
618
620
  expect(testFlow).toBeDefined();
619
621
  if (testFlow !== null && testFlow !== undefined) {
620
622
  validateSubmitQuestionnaireCommand(testFlow);
@@ -625,21 +627,21 @@ flow('questionnaires-test', () => {
625
627
  });
626
628
 
627
629
  it('correctly distinguishes between State and Event types in given clauses with empty when', async () => {
628
- const flows = await getNarratives({ vfs, root, pattern, fastFsScan: true });
630
+ const flows = await getScenes({ vfs, root, pattern, fastFsScan: true });
629
631
  const model = flows.toModel();
630
632
 
631
- const mixedGivenFlow = model.narratives.find((f) => f.name === 'Mixed Given Types');
633
+ const mixedGivenFlow = model.scenes.find((f) => f.name === 'Mixed Given Types');
632
634
  expect(mixedGivenFlow).toBeDefined();
633
635
 
634
636
  if (!mixedGivenFlow) return;
635
637
 
636
- const querySlice = mixedGivenFlow.slices.find((s) => s.name === 'system status check');
637
- expect(querySlice).toBeDefined();
638
- expect(querySlice?.type).toBe('query');
638
+ const queryMoment = mixedGivenFlow.moments.find((s) => s.name === 'system status check');
639
+ expect(queryMoment).toBeDefined();
640
+ expect(queryMoment?.type).toBe('query');
639
641
 
640
- if (querySlice?.type !== 'query') return;
642
+ if (queryMoment?.type !== 'query') return;
641
643
 
642
- const example = querySlice.server.specs[0].rules[0]?.examples[0];
644
+ const example = queryMoment.server.specs[0].rules[0]?.examples[0];
643
645
  expect(example).toBeDefined();
644
646
 
645
647
  if (example !== null && example !== undefined) {
@@ -651,7 +653,7 @@ flow('questionnaires-test', () => {
651
653
  });
652
654
 
653
655
  it('does not emit empty generics or empty when clauses', async () => {
654
- const flows = await getNarratives({
656
+ const flows = await getScenes({
655
657
  vfs,
656
658
  root,
657
659
  pattern: /(?:^|\/)questionnaires\.narrative\.(?:ts|tsx|js|jsx|mjs|cjs)$/,
@@ -668,7 +670,7 @@ flow('questionnaires-test', () => {
668
670
  });
669
671
 
670
672
  it('should not generate phantom messages with empty names', async () => {
671
- const flows = await getNarratives({
673
+ const flows = await getScenes({
672
674
  vfs,
673
675
  root: root,
674
676
  pattern: /(?:^|\/)questionnaires\.narrative\.(?:ts|tsx|js|jsx|mjs|cjs)$/,
@@ -691,7 +693,7 @@ flow('questionnaires-test', () => {
691
693
  it('should convert all given events to eventRef', async (): Promise<void> => {
692
694
  const memoryVfs = new InMemoryFileStore();
693
695
  const todoSummaryFlowContent = `
694
- import { flow, query, specs, rule, example, type Event, type State } from '@auto-engineer/narrative';
696
+ import { scene, query, specs, rule, example, type Event, type State } from '@auto-engineer/narrative';
695
697
 
696
698
  type TodoAdded = Event<
697
699
  'TodoAdded',
@@ -731,7 +733,7 @@ type TodoListSummary = State<
731
733
  }
732
734
  >;
733
735
 
734
- flow('Todo List', () => {
736
+ scene('Todo List', () => {
735
737
  query('views completion summary')
736
738
  .server(() => {
737
739
  specs(() => {
@@ -780,20 +782,20 @@ flow('Todo List', () => {
780
782
 
781
783
  await memoryVfs.write('/test/todo-summary.narrative.ts', new TextEncoder().encode(todoSummaryFlowContent));
782
784
 
783
- const flows = await getNarratives({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
785
+ const flows = await getScenes({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
784
786
  const model = flows.toModel();
785
787
 
786
- const todoFlow = model.narratives.find((f) => f.name === 'Todo List');
788
+ const todoFlow = model.scenes.find((f) => f.name === 'Todo List');
787
789
  expect(todoFlow).toBeDefined();
788
790
 
789
791
  if (!todoFlow) return;
790
792
 
791
- const summarySlice = todoFlow.slices.find((s) => s.name === 'views completion summary');
792
- expect(summarySlice?.type).toBe('query');
793
+ const summaryMoment = todoFlow.moments.find((s) => s.name === 'views completion summary');
794
+ expect(summaryMoment?.type).toBe('query');
793
795
 
794
- if (summarySlice?.type !== 'query') return;
796
+ if (summaryMoment?.type !== 'query') return;
795
797
 
796
- const example = summarySlice.server.specs[0].rules[0]?.examples[0];
798
+ const example = summaryMoment.server.specs[0].rules[0]?.examples[0];
797
799
  expect(example).toBeDefined();
798
800
  expect(example.steps).toBeDefined();
799
801
  expect(Array.isArray(example.steps)).toBe(true);
@@ -849,11 +851,11 @@ function validateTodoMessages(model: Model): void {
849
851
  expect(todoListSummaryState?.type).toBe('state');
850
852
  }
851
853
 
852
- function validateSubmitQuestionnaireCommand(questionnaireFlow: Narrative): void {
853
- const submitSlice = questionnaireFlow.slices.find((s) => s.name === 'submits questionnaire');
854
- expect(submitSlice?.type).toBe('command');
855
- if (submitSlice?.type === 'command') {
856
- const example = submitSlice.server?.specs?.[0]?.rules[0]?.examples[0];
854
+ function validateSubmitQuestionnaireCommand(questionnaireFlow: Scene): void {
855
+ const submitMoment = questionnaireFlow.moments.find((s) => s.name === 'submits questionnaire');
856
+ expect(submitMoment?.type).toBe('command');
857
+ if (submitMoment?.type === 'command') {
858
+ const example = submitMoment.server?.specs?.[0]?.rules[0]?.examples[0];
857
859
  const whenStep = example?.steps?.find((s) => s.keyword === 'When');
858
860
  if (whenStep && 'text' in whenStep) {
859
861
  expect(whenStep.text).toBe('SubmitQuestionnaire');
@@ -866,10 +868,10 @@ function validateQuestionAnsweredEvent(model: Model): void {
866
868
  expect(questionAnsweredMessage?.type).toBe('event');
867
869
  }
868
870
 
869
- function validateGivenSectionEventRefs(questionnaireFlow: Narrative): void {
870
- const viewsSlice = questionnaireFlow.slices.find((s) => s.name === 'views progress');
871
- if (viewsSlice?.type === 'query') {
872
- const example = viewsSlice.server?.specs?.[0]?.rules[0]?.examples[0];
871
+ function validateGivenSectionEventRefs(questionnaireFlow: Scene): void {
872
+ const viewsMoment = questionnaireFlow.moments.find((s) => s.name === 'views progress');
873
+ if (viewsMoment?.type === 'query') {
874
+ const example = viewsMoment.server?.specs?.[0]?.rules[0]?.examples[0];
873
875
  if (example?.steps !== undefined && Array.isArray(example.steps)) {
874
876
  const givenStep = example.steps.find((s) => s.keyword === 'Given');
875
877
  if (givenStep && 'text' in givenStep) {
@@ -957,7 +959,7 @@ async function createQuestionnaireBugTestModel(): Promise<Model> {
957
959
  const memoryVfs = new InMemoryFileStore();
958
960
  const questionnaireFlowContent = getQuestionnaireFlowContent();
959
961
  await memoryVfs.write('/test/questionnaires-bug.narrative.ts', new TextEncoder().encode(questionnaireFlowContent));
960
- const flows = await getNarratives({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
962
+ const flows = await getScenes({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
961
963
  return flows.toModel();
962
964
  }
963
965
 
@@ -967,7 +969,7 @@ import {
967
969
  command,
968
970
  query,
969
971
  experience,
970
- flow,
972
+ scene,
971
973
  describe,
972
974
  it,
973
975
  specs,
@@ -1017,7 +1019,7 @@ type SubmitQuestionnaire = Command<
1017
1019
  }
1018
1020
  >;
1019
1021
 
1020
- flow('Questionnaires', 'Q9m2Kp4Lx', () => {
1022
+ scene('Questionnaires', 'Q9m2Kp4Lx', () => {
1021
1023
  command('sends the questionnaire link', 'S2b5Cp7Dz')
1022
1024
  .server(() => {
1023
1025
  specs(() => {
@@ -1086,15 +1088,15 @@ flow('Questionnaires', 'Q9m2Kp4Lx', () => {
1086
1088
 
1087
1089
  function validateQuestionnaireBugFix(model: Model): void {
1088
1090
  const questionnaireFlow = getQuestionnaireFlowFromModel(model);
1089
- const submitSlice = getSubmitSlice(questionnaireFlow);
1090
- const submitExample = getSubmitExample(submitSlice);
1091
+ const submitMoment = getSubmitMoment(questionnaireFlow);
1092
+ const submitExample = getSubmitExample(submitMoment);
1091
1093
 
1092
1094
  validateSubmitCommandRef(submitExample);
1093
- validateLinkSliceCommandRef(questionnaireFlow);
1095
+ validateLinkMomentCommandRef(questionnaireFlow);
1094
1096
  }
1095
1097
 
1096
- function getQuestionnaireFlowFromModel(model: Model): Narrative {
1097
- const questionnaireFlow = model.narratives.find((f) => f.name === 'Questionnaires');
1098
+ function getQuestionnaireFlowFromModel(model: Model): Scene {
1099
+ const questionnaireFlow = model.scenes.find((f) => f.name === 'Questionnaires');
1098
1100
  expect(questionnaireFlow).toBeDefined();
1099
1101
  if (questionnaireFlow === null || questionnaireFlow === undefined) {
1100
1102
  throw new Error('Questionnaire flow not found');
@@ -1102,26 +1104,26 @@ function getQuestionnaireFlowFromModel(model: Model): Narrative {
1102
1104
  return questionnaireFlow;
1103
1105
  }
1104
1106
 
1105
- function getSubmitSlice(questionnaireFlow: Narrative): {
1107
+ function getSubmitMoment(questionnaireFlow: Scene): {
1106
1108
  type: 'command';
1107
1109
  server: { specs: { type: 'gherkin'; feature: string; rules: { examples: unknown[] }[] }[] };
1108
1110
  } {
1109
- const submitSlice = questionnaireFlow.slices.find((s) => s.name === 'submits the questionnaire');
1110
- expect(submitSlice).toBeDefined();
1111
- expect(submitSlice?.type).toBe('command');
1112
- if (submitSlice?.type !== 'command') {
1111
+ const submitMoment = questionnaireFlow.moments.find((s) => s.name === 'submits the questionnaire');
1112
+ expect(submitMoment).toBeDefined();
1113
+ expect(submitMoment?.type).toBe('command');
1114
+ if (submitMoment?.type !== 'command') {
1113
1115
  throw new Error('Submit slice is not a command');
1114
1116
  }
1115
- return submitSlice as {
1117
+ return submitMoment as {
1116
1118
  type: 'command';
1117
1119
  server: { specs: { type: 'gherkin'; feature: string; rules: { examples: unknown[] }[] }[] };
1118
1120
  };
1119
1121
  }
1120
1122
 
1121
- function getSubmitExample(submitSlice: {
1123
+ function getSubmitExample(submitMoment: {
1122
1124
  server: { specs: { type: 'gherkin'; feature: string; rules: { examples: unknown[] }[] }[] };
1123
1125
  }): unknown {
1124
- const rule = submitSlice.server?.specs?.[0]?.rules[0];
1126
+ const rule = submitMoment.server?.specs?.[0]?.rules[0];
1125
1127
  expect(rule).toBeDefined();
1126
1128
  expect(rule?.examples).toHaveLength(1);
1127
1129
  const example = rule?.examples[0];
@@ -1141,11 +1143,11 @@ function validateSubmitCommandRef(example: unknown): void {
1141
1143
  }
1142
1144
  }
1143
1145
 
1144
- function validateLinkSliceCommandRef(questionnaireFlow: Narrative): void {
1145
- const linkSlice = questionnaireFlow.slices.find((s) => s.name === 'sends the questionnaire link');
1146
- expect(linkSlice?.type).toBe('command');
1147
- if (linkSlice?.type === 'command') {
1148
- const linkExample = linkSlice.server?.specs?.[0]?.rules[0]?.examples[0];
1146
+ function validateLinkMomentCommandRef(questionnaireFlow: Scene): void {
1147
+ const linkMoment = questionnaireFlow.moments.find((s) => s.name === 'sends the questionnaire link');
1148
+ expect(linkMoment?.type).toBe('command');
1149
+ if (linkMoment?.type === 'command') {
1150
+ const linkExample = linkMoment.server?.specs?.[0]?.rules[0]?.examples[0];
1149
1151
  const ex = linkExample as { steps?: { keyword: string; text?: string }[] };
1150
1152
  const whenStep = ex?.steps?.find((s) => s.keyword === 'When');
1151
1153
  if (whenStep && 'text' in whenStep) {
@@ -1156,8 +1158,8 @@ function validateLinkSliceCommandRef(questionnaireFlow: Narrative): void {
1156
1158
 
1157
1159
  function validateCommandRef(model: Model): void {
1158
1160
  const questionnaireFlow = getQuestionnaireFlowFromModel(model);
1159
- const submitSlice = getSubmitSliceFromFlow(questionnaireFlow);
1160
- const serverSpecs = getServerSpecsFromSlice(submitSlice);
1161
+ const submitMoment = getSubmitMomentFromFlow(questionnaireFlow);
1162
+ const serverSpecs = getServerSpecsFromMoment(submitMoment);
1161
1163
  const rule = getFirstRuleFromSpecs(serverSpecs);
1162
1164
  const example = getFirstExampleFromRule(rule);
1163
1165
 
@@ -1165,18 +1167,18 @@ function validateCommandRef(model: Model): void {
1165
1167
  validateThenEvents(example);
1166
1168
  }
1167
1169
 
1168
- function getSubmitSliceFromFlow(questionnaireFlow: Narrative): unknown {
1169
- const submitSlice = questionnaireFlow.slices.find((s) => s.name === 'submits the questionnaire');
1170
- expect(submitSlice).toBeDefined();
1171
- expect(submitSlice?.type).toBe('command');
1172
- if (submitSlice?.type !== 'command') {
1170
+ function getSubmitMomentFromFlow(questionnaireFlow: Scene): unknown {
1171
+ const submitMoment = questionnaireFlow.moments.find((s) => s.name === 'submits the questionnaire');
1172
+ expect(submitMoment).toBeDefined();
1173
+ expect(submitMoment?.type).toBe('command');
1174
+ if (submitMoment?.type !== 'command') {
1173
1175
  throw new Error('Submit slice is not a command');
1174
1176
  }
1175
- return submitSlice;
1177
+ return submitMoment;
1176
1178
  }
1177
1179
 
1178
- function getServerSpecsFromSlice(submitSlice: unknown): unknown {
1179
- const slice = submitSlice as { server?: { specs?: unknown[] } };
1180
+ function getServerSpecsFromMoment(submitMoment: unknown): unknown {
1181
+ const slice = submitMoment as { server?: { specs?: unknown[] } };
1180
1182
  const serverSpecs = slice.server?.specs;
1181
1183
  expect(serverSpecs).toBeDefined();
1182
1184
  expect(Array.isArray(serverSpecs)).toBe(true);
@@ -1242,16 +1244,16 @@ function validateThenEvents(example: unknown): void {
1242
1244
  }
1243
1245
 
1244
1246
  describe('modules in toModel()', () => {
1245
- it('should derive modules from narratives with different sourceFiles', async () => {
1247
+ it('should derive modules from scenes with different sourceFiles', async () => {
1246
1248
  const memoryVfs = new InMemoryFileStore();
1247
1249
 
1248
1250
  const ordersContent = `
1249
- import { flow, command, specs, rule, example, type Command, type Event } from '@auto-engineer/narrative';
1251
+ import { scene, command, specs, rule, example, type Command, type Event } from '@auto-engineer/narrative';
1250
1252
 
1251
1253
  type CreateOrder = Command<'CreateOrder', { orderId: string }>;
1252
1254
  type OrderCreated = Event<'OrderCreated', { orderId: string; createdAt: Date }>;
1253
1255
 
1254
- flow('Orders', () => {
1256
+ scene('Orders', () => {
1255
1257
  command('create order')
1256
1258
  .server(() => {
1257
1259
  specs(() => {
@@ -1266,12 +1268,12 @@ flow('Orders', () => {
1266
1268
  `;
1267
1269
 
1268
1270
  const usersContent = `
1269
- import { flow, command, specs, rule, example, type Command, type Event } from '@auto-engineer/narrative';
1271
+ import { scene, command, specs, rule, example, type Command, type Event } from '@auto-engineer/narrative';
1270
1272
 
1271
1273
  type CreateUser = Command<'CreateUser', { userId: string; name: string }>;
1272
1274
  type UserCreated = Event<'UserCreated', { userId: string; name: string; createdAt: Date }>;
1273
1275
 
1274
- flow('Users', () => {
1276
+ scene('Users', () => {
1275
1277
  command('create user')
1276
1278
  .server(() => {
1277
1279
  specs(() => {
@@ -1288,7 +1290,7 @@ flow('Users', () => {
1288
1290
  await memoryVfs.write('/test/orders.narrative.ts', new TextEncoder().encode(ordersContent));
1289
1291
  await memoryVfs.write('/test/users.narrative.ts', new TextEncoder().encode(usersContent));
1290
1292
 
1291
- const flows = await getNarratives({
1293
+ const flows = await getScenes({
1292
1294
  vfs: memoryVfs,
1293
1295
  root: '/test',
1294
1296
  pattern: /\.narrative\.ts$/,
@@ -1317,12 +1319,12 @@ flow('Users', () => {
1317
1319
  const memoryVfs = new InMemoryFileStore();
1318
1320
 
1319
1321
  const content = `
1320
- import { flow, command, specs, rule, example, type Command, type Event } from '@auto-engineer/narrative';
1322
+ import { scene, command, specs, rule, example, type Command, type Event } from '@auto-engineer/narrative';
1321
1323
 
1322
1324
  type CreateOrder = Command<'CreateOrder', { orderId: string }>;
1323
1325
  type OrderCreated = Event<'OrderCreated', { orderId: string }>;
1324
1326
 
1325
- flow('Orders', () => {
1327
+ scene('Orders', () => {
1326
1328
  command('create order')
1327
1329
  .server(() => {
1328
1330
  specs(() => {
@@ -1338,7 +1340,7 @@ flow('Orders', () => {
1338
1340
 
1339
1341
  await memoryVfs.write('/test/orders.narrative.ts', new TextEncoder().encode(content));
1340
1342
 
1341
- const flows = await getNarratives({
1343
+ const flows = await getScenes({
1342
1344
  vfs: memoryVfs,
1343
1345
  root: '/test',
1344
1346
  pattern: /\.narrative\.ts$/,
@@ -1354,17 +1356,17 @@ flow('Orders', () => {
1354
1356
  expect(declaredNames).toContain('OrderCreated');
1355
1357
  });
1356
1358
 
1357
- it('should group narratives from same sourceFile into one module', async () => {
1359
+ it('should group scenes from same sourceFile into one module', async () => {
1358
1360
  const memoryVfs = new InMemoryFileStore();
1359
1361
 
1360
1362
  const content = `
1361
- import { flow, command, query, specs, rule, example, type Command, type Event, type State } from '@auto-engineer/narrative';
1363
+ import { scene, command, query, specs, rule, example, type Command, type Event, type State } from '@auto-engineer/narrative';
1362
1364
 
1363
1365
  type CreateTodo = Command<'CreateTodo', { todoId: string }>;
1364
1366
  type TodoCreated = Event<'TodoCreated', { todoId: string }>;
1365
1367
  type TodoList = State<'TodoList', { todos: string[] }>;
1366
1368
 
1367
- flow('Create Todos', () => {
1369
+ scene('Create Todos', () => {
1368
1370
  command('add todo')
1369
1371
  .server(() => {
1370
1372
  specs(() => {
@@ -1377,7 +1379,7 @@ flow('Create Todos', () => {
1377
1379
  });
1378
1380
  });
1379
1381
 
1380
- flow('View Todos', () => {
1382
+ scene('View Todos', () => {
1381
1383
  query('list todos')
1382
1384
  .server(() => {
1383
1385
  specs(() => {
@@ -1394,7 +1396,7 @@ flow('View Todos', () => {
1394
1396
 
1395
1397
  await memoryVfs.write('/test/todos.narrative.ts', new TextEncoder().encode(content));
1396
1398
 
1397
- const flows = await getNarratives({
1399
+ const flows = await getScenes({
1398
1400
  vfs: memoryVfs,
1399
1401
  root: '/test',
1400
1402
  pattern: /\.narrative\.ts$/,
@@ -1403,23 +1405,23 @@ flow('View Todos', () => {
1403
1405
  const model = flows.toModel();
1404
1406
 
1405
1407
  expect(model.modules).toHaveLength(1);
1406
- expect(model.modules[0].contains.narrativeIds).toHaveLength(2);
1408
+ expect(model.modules[0].contains.sceneIds).toHaveLength(2);
1407
1409
 
1408
- const narrativeNames = model.narratives.map((n) => n.name);
1409
- expect(narrativeNames).toContain('Create Todos');
1410
- expect(narrativeNames).toContain('View Todos');
1410
+ const sceneNames = model.scenes.map((n) => n.name);
1411
+ expect(sceneNames).toContain('Create Todos');
1412
+ expect(sceneNames).toContain('View Todos');
1411
1413
  });
1412
1414
 
1413
1415
  it('should validate model with modules passes schema', async () => {
1414
1416
  const memoryVfs = new InMemoryFileStore();
1415
1417
 
1416
1418
  const content = `
1417
- import { flow, command, specs, rule, example, type Command, type Event } from '@auto-engineer/narrative';
1419
+ import { scene, command, specs, rule, example, type Command, type Event } from '@auto-engineer/narrative';
1418
1420
 
1419
1421
  type DoSomething = Command<'DoSomething', { id: string }>;
1420
1422
  type SomethingDone = Event<'SomethingDone', { id: string }>;
1421
1423
 
1422
- flow('Test', () => {
1424
+ scene('Test', () => {
1423
1425
  command('do something')
1424
1426
  .server(() => {
1425
1427
  specs(() => {
@@ -1435,7 +1437,7 @@ flow('Test', () => {
1435
1437
 
1436
1438
  await memoryVfs.write('/test/test.narrative.ts', new TextEncoder().encode(content));
1437
1439
 
1438
- const flows = await getNarratives({
1440
+ const flows = await getScenes({
1439
1441
  vfs: memoryVfs,
1440
1442
  root: '/test',
1441
1443
  pattern: /\.narrative\.ts$/,
@@ -1457,12 +1459,12 @@ describe('projection DSL methods', () => {
1457
1459
  it('should generate correct origin for singleton projection', async () => {
1458
1460
  const memoryVfs = new InMemoryFileStore();
1459
1461
  const flowContent = `
1460
- import { flow, query, specs, rule, example, data, source, type Event, type State } from '@auto-engineer/narrative';
1462
+ import { scene, query, specs, rule, example, data, source, type Event, type State } from '@auto-engineer/narrative';
1461
1463
 
1462
1464
  type TodoAdded = Event<'TodoAdded', { todoId: string; description: string; addedAt: Date }>;
1463
1465
  type TodoListSummary = State<'TodoListSummary', { summaryId: string; totalTodos: number }>;
1464
1466
 
1465
- flow('Projection Test', () => {
1467
+ scene('Projection Test', () => {
1466
1468
  query('views summary')
1467
1469
  .server(() => {
1468
1470
  specs(() => {
@@ -1480,20 +1482,20 @@ flow('Projection Test', () => {
1480
1482
 
1481
1483
  await memoryVfs.write('/test/projection.narrative.ts', new TextEncoder().encode(flowContent));
1482
1484
 
1483
- const flows = await getNarratives({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
1485
+ const flows = await getScenes({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
1484
1486
  const model = flows.toModel();
1485
1487
 
1486
- const projectionFlow = model.narratives.find((f) => f.name === 'Projection Test');
1488
+ const projectionFlow = model.scenes.find((f) => f.name === 'Projection Test');
1487
1489
  expect(projectionFlow).toBeDefined();
1488
1490
 
1489
1491
  if (!projectionFlow) return;
1490
1492
 
1491
- const summarySlice = projectionFlow.slices.find((s) => s.name === 'views summary');
1492
- expect(summarySlice?.type).toBe('query');
1493
+ const summaryMoment = projectionFlow.moments.find((s) => s.name === 'views summary');
1494
+ expect(summaryMoment?.type).toBe('query');
1493
1495
 
1494
- if (summarySlice?.type !== 'query') return;
1496
+ if (summaryMoment?.type !== 'query') return;
1495
1497
 
1496
- const data = summarySlice.server.data;
1498
+ const data = summaryMoment.server.data;
1497
1499
  expect(data).toBeDefined();
1498
1500
  expect(data?.items).toHaveLength(1);
1499
1501
 
@@ -1509,12 +1511,12 @@ flow('Projection Test', () => {
1509
1511
  it('should generate correct origin for regular projection with single idField', async () => {
1510
1512
  const memoryVfs = new InMemoryFileStore();
1511
1513
  const flowContent = `
1512
- import { flow, query, specs, rule, example, data, source, type Event, type State } from '@auto-engineer/narrative';
1514
+ import { scene, query, specs, rule, example, data, source, type Event, type State } from '@auto-engineer/narrative';
1513
1515
 
1514
1516
  type TodoAdded = Event<'TodoAdded', { todoId: string; description: string; addedAt: Date }>;
1515
1517
  type TodoState = State<'TodoState', { todoId: string; description: string; status: string }>;
1516
1518
 
1517
- flow('Projection Test', () => {
1519
+ scene('Projection Test', () => {
1518
1520
  query('views todo')
1519
1521
  .server(() => {
1520
1522
  specs(() => {
@@ -1532,20 +1534,20 @@ flow('Projection Test', () => {
1532
1534
 
1533
1535
  await memoryVfs.write('/test/projection.narrative.ts', new TextEncoder().encode(flowContent));
1534
1536
 
1535
- const flows = await getNarratives({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
1537
+ const flows = await getScenes({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
1536
1538
  const model = flows.toModel();
1537
1539
 
1538
- const projectionFlow = model.narratives.find((f) => f.name === 'Projection Test');
1540
+ const projectionFlow = model.scenes.find((f) => f.name === 'Projection Test');
1539
1541
  expect(projectionFlow).toBeDefined();
1540
1542
 
1541
1543
  if (!projectionFlow) return;
1542
1544
 
1543
- const todoSlice = projectionFlow.slices.find((s) => s.name === 'views todo');
1544
- expect(todoSlice?.type).toBe('query');
1545
+ const todoMoment = projectionFlow.moments.find((s) => s.name === 'views todo');
1546
+ expect(todoMoment?.type).toBe('query');
1545
1547
 
1546
- if (todoSlice?.type !== 'query') return;
1548
+ if (todoMoment?.type !== 'query') return;
1547
1549
 
1548
- const data = todoSlice.server.data;
1550
+ const data = todoMoment.server.data;
1549
1551
  expect(data).toBeDefined();
1550
1552
  expect(data?.items).toHaveLength(1);
1551
1553
 
@@ -1561,12 +1563,12 @@ flow('Projection Test', () => {
1561
1563
  it('should generate correct origin for composite projection with multiple idFields', async () => {
1562
1564
  const memoryVfs = new InMemoryFileStore();
1563
1565
  const flowContent = `
1564
- import { flow, query, specs, rule, example, data, source, type Event, type State } from '@auto-engineer/narrative';
1566
+ import { scene, query, specs, rule, example, data, source, type Event, type State } from '@auto-engineer/narrative';
1565
1567
 
1566
1568
  type UserProjectAssigned = Event<'UserProjectAssigned', { userId: string; projectId: string; assignedAt: Date }>;
1567
1569
  type UserProjectState = State<'UserProjectState', { userId: string; projectId: string; role: string }>;
1568
1570
 
1569
- flow('Projection Test', () => {
1571
+ scene('Projection Test', () => {
1570
1572
  query('views user project')
1571
1573
  .server(() => {
1572
1574
  specs(() => {
@@ -1584,20 +1586,20 @@ flow('Projection Test', () => {
1584
1586
 
1585
1587
  await memoryVfs.write('/test/projection.narrative.ts', new TextEncoder().encode(flowContent));
1586
1588
 
1587
- const flows = await getNarratives({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
1589
+ const flows = await getScenes({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
1588
1590
  const model = flows.toModel();
1589
1591
 
1590
- const projectionFlow = model.narratives.find((f) => f.name === 'Projection Test');
1592
+ const projectionFlow = model.scenes.find((f) => f.name === 'Projection Test');
1591
1593
  expect(projectionFlow).toBeDefined();
1592
1594
 
1593
1595
  if (!projectionFlow) return;
1594
1596
 
1595
- const userProjectSlice = projectionFlow.slices.find((s) => s.name === 'views user project');
1596
- expect(userProjectSlice?.type).toBe('query');
1597
+ const userProjectMoment = projectionFlow.moments.find((s) => s.name === 'views user project');
1598
+ expect(userProjectMoment?.type).toBe('query');
1597
1599
 
1598
- if (userProjectSlice?.type !== 'query') return;
1600
+ if (userProjectMoment?.type !== 'query') return;
1599
1601
 
1600
- const data = userProjectSlice.server.data;
1602
+ const data = userProjectMoment.server.data;
1601
1603
  expect(data).toBeDefined();
1602
1604
  expect(data?.items).toHaveLength(1);
1603
1605
 
@@ -1613,7 +1615,7 @@ flow('Projection Test', () => {
1613
1615
  it('should validate all three projection patterns together', async () => {
1614
1616
  const memoryVfs = new InMemoryFileStore();
1615
1617
  const flowContent = `
1616
- import { flow, query, specs, rule, example, data, source, type Event, type State } from '@auto-engineer/narrative';
1618
+ import { scene, query, specs, rule, example, data, source, type Event, type State } from '@auto-engineer/narrative';
1617
1619
 
1618
1620
  type TodoAdded = Event<'TodoAdded', { todoId: string; userId: string; projectId: string; description: string; addedAt: Date }>;
1619
1621
 
@@ -1621,7 +1623,7 @@ type TodoListSummary = State<'TodoListSummary', { summaryId: string; totalTodos:
1621
1623
  type TodoState = State<'TodoState', { todoId: string; description: string; status: string }>;
1622
1624
  type UserProjectTodos = State<'UserProjectTodos', { userId: string; projectId: string; todos: string[] }>;
1623
1625
 
1624
- flow('All Projection Patterns', () => {
1626
+ scene('All Projection Patterns', () => {
1625
1627
  query('views summary')
1626
1628
  .server(() => {
1627
1629
  specs(() => {
@@ -1665,7 +1667,7 @@ flow('All Projection Patterns', () => {
1665
1667
 
1666
1668
  await memoryVfs.write('/test/projection.narrative.ts', new TextEncoder().encode(flowContent));
1667
1669
 
1668
- const flows = await getNarratives({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
1670
+ const flows = await getScenes({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
1669
1671
  const model = flows.toModel();
1670
1672
 
1671
1673
  const parseResult = modelSchema.safeParse(model);
@@ -1674,16 +1676,16 @@ flow('All Projection Patterns', () => {
1674
1676
  }
1675
1677
  expect(parseResult.success).toBe(true);
1676
1678
 
1677
- const projectionFlow = model.narratives.find((f) => f.name === 'All Projection Patterns');
1679
+ const projectionFlow = model.scenes.find((f) => f.name === 'All Projection Patterns');
1678
1680
  expect(projectionFlow).toBeDefined();
1679
1681
 
1680
1682
  if (!projectionFlow) return;
1681
1683
 
1682
- expect(projectionFlow.slices).toHaveLength(3);
1684
+ expect(projectionFlow.moments).toHaveLength(3);
1683
1685
 
1684
- const summarySlice = projectionFlow.slices.find((s) => s.name === 'views summary');
1685
- if (summarySlice?.type === 'query') {
1686
- const data = summarySlice.server.data;
1686
+ const summaryMoment = projectionFlow.moments.find((s) => s.name === 'views summary');
1687
+ if (summaryMoment?.type === 'query') {
1688
+ const data = summaryMoment.server.data;
1687
1689
  expect(data?.items?.[0].origin).toMatchObject({
1688
1690
  type: 'projection',
1689
1691
  name: 'TodoSummary',
@@ -1691,9 +1693,9 @@ flow('All Projection Patterns', () => {
1691
1693
  });
1692
1694
  }
1693
1695
 
1694
- const todoSlice = projectionFlow.slices.find((s) => s.name === 'views todo');
1695
- if (todoSlice?.type === 'query') {
1696
- const data = todoSlice.server.data;
1696
+ const todoMoment = projectionFlow.moments.find((s) => s.name === 'views todo');
1697
+ if (todoMoment?.type === 'query') {
1698
+ const data = todoMoment.server.data;
1697
1699
  expect(data?.items?.[0].origin).toMatchObject({
1698
1700
  type: 'projection',
1699
1701
  name: 'Todos',
@@ -1701,9 +1703,9 @@ flow('All Projection Patterns', () => {
1701
1703
  });
1702
1704
  }
1703
1705
 
1704
- const userProjectSlice = projectionFlow.slices.find((s) => s.name === 'views user project todos');
1705
- if (userProjectSlice?.type === 'query') {
1706
- const data = userProjectSlice.server.data;
1706
+ const userProjectMoment = projectionFlow.moments.find((s) => s.name === 'views user project todos');
1707
+ if (userProjectMoment?.type === 'query') {
1708
+ const data = userProjectMoment.server.data;
1707
1709
  expect(data?.items?.[0].origin).toMatchObject({
1708
1710
  type: 'projection',
1709
1711
  name: 'UserProjectTodos',
@@ -1716,12 +1718,12 @@ flow('All Projection Patterns', () => {
1716
1718
  const memoryVfs = new InMemoryFileStore();
1717
1719
 
1718
1720
  const flowContent = `
1719
- import { flow, command, query, specs, rule, example, data, sink, source, type Event, type State } from '@auto-engineer/narrative';
1721
+ import { scene, command, query, specs, rule, example, data, sink, source, type Event, type State } from '@auto-engineer/narrative';
1720
1722
 
1721
1723
  type OrderPlaced = Event<'OrderPlaced', { orderId: string; amount: number }>;
1722
1724
  type OrderState = State<'OrderState', { orderId: string; status: string }>;
1723
1725
 
1724
- flow('Data Item IDs', () => {
1726
+ scene('Data Item IDs', () => {
1725
1727
  command('places order')
1726
1728
  .server(() => {
1727
1729
  specs(() => {
@@ -1755,41 +1757,41 @@ flow('Data Item IDs', () => {
1755
1757
 
1756
1758
  await memoryVfs.write('/test/data-ids.narrative.ts', new TextEncoder().encode(flowContent));
1757
1759
 
1758
- const flows = await getNarratives({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
1760
+ const flows = await getScenes({ vfs: memoryVfs, root: '/test', pattern, fastFsScan: true });
1759
1761
  const model = flows.toModel();
1760
1762
 
1761
1763
  const parseResult = modelSchema.safeParse(model);
1762
1764
  expect(parseResult.success).toBe(true);
1763
1765
 
1764
- const dataIdsFlow = model.narratives.find((f) => f.name === 'Data Item IDs');
1766
+ const dataIdsFlow = model.scenes.find((f) => f.name === 'Data Item IDs');
1765
1767
  expect(dataIdsFlow).toBeDefined();
1766
1768
 
1767
1769
  if (!dataIdsFlow) return;
1768
1770
 
1769
- const commandSlice = dataIdsFlow.slices.find((s) => s.name === 'places order');
1770
- if (commandSlice?.type === 'command') {
1771
- const sinkData = commandSlice.server.data;
1771
+ const commandMoment = dataIdsFlow.moments.find((s) => s.name === 'places order');
1772
+ if (commandMoment?.type === 'command') {
1773
+ const sinkData = commandMoment.server.data;
1772
1774
  expect(sinkData?.items).toHaveLength(1);
1773
1775
  expect(sinkData?.items?.[0].id).toBe('SINK-001');
1774
1776
  }
1775
1777
 
1776
- const querySlice = dataIdsFlow.slices.find((s) => s.name === 'views order status');
1777
- if (querySlice?.type === 'query') {
1778
- const sourceData = querySlice.server.data;
1778
+ const queryMoment = dataIdsFlow.moments.find((s) => s.name === 'views order status');
1779
+ if (queryMoment?.type === 'query') {
1780
+ const sourceData = queryMoment.server.data;
1779
1781
  expect(sourceData?.items).toHaveLength(1);
1780
1782
  expect(sourceData?.items?.[0].id).toBe('SOURCE-001');
1781
1783
  }
1782
1784
  });
1783
1785
  });
1784
1786
 
1785
- describe('round-trip: model -> narrative code -> VFS -> getNarratives -> toModel', { timeout: 30_000 }, () => {
1787
+ describe('round-trip: model -> narrative code -> VFS -> getScenes -> toModel', { timeout: 30_000 }, () => {
1786
1788
  it('preserves step text values through full round-trip', async () => {
1787
1789
  const inputModel: Model = {
1788
1790
  variant: 'specs',
1789
- narratives: [
1791
+ scenes: [
1790
1792
  {
1791
1793
  name: 'Stay management',
1792
- slices: [
1794
+ moments: [
1793
1795
  {
1794
1796
  type: 'command',
1795
1797
  name: 'Publish stay',
@@ -1865,14 +1867,14 @@ describe('round-trip: model -> narrative code -> VFS -> getNarratives -> toModel
1865
1867
  const generated = await modelToNarrative(inputModel);
1866
1868
 
1867
1869
  const vfs = new InMemoryFileStore();
1868
- clearGetNarrativesCache();
1870
+ clearGetScenesCache();
1869
1871
 
1870
1872
  for (const file of generated.files) {
1871
1873
  const filePath = `/project/${file.path}`;
1872
1874
  await vfs.write(filePath, new TextEncoder().encode(file.code));
1873
1875
  }
1874
1876
 
1875
- const result = await getNarratives({
1877
+ const result = await getScenes({
1876
1878
  vfs,
1877
1879
  root: '/project',
1878
1880
  pattern: /\.(narrative)\.(ts)$/,
@@ -1881,12 +1883,12 @@ describe('round-trip: model -> narrative code -> VFS -> getNarratives -> toModel
1881
1883
 
1882
1884
  const roundTrippedModel = result.toModel();
1883
1885
 
1884
- const stayNarrative = roundTrippedModel.narratives.find((n) => n.name === 'Stay management');
1885
- const publishSlice = stayNarrative!.slices.find((s) => s.name === 'Publish stay');
1886
- expect(publishSlice!.type).toBe('command');
1886
+ const stayNarrative = roundTrippedModel.scenes.find((n) => n.name === 'Stay management');
1887
+ const publishMoment = stayNarrative!.moments.find((s) => s.name === 'Publish stay');
1888
+ expect(publishMoment!.type).toBe('command');
1887
1889
 
1888
- if (publishSlice?.type === 'command') {
1889
- const example = publishSlice.server.specs[0].rules[0].examples[0];
1890
+ if (publishMoment?.type === 'command') {
1891
+ const example = publishMoment.server.specs[0].rules[0].examples[0];
1890
1892
  expect(example.steps).toEqual([
1891
1893
  { keyword: 'Given', text: 'StayCreated', docString: { stayId: 'stay_1', title: 'Beach house' } },
1892
1894
  { keyword: 'When', text: 'PublishStay', docString: { stayId: 'stay_1' } },
@@ -1902,10 +1904,10 @@ describe('round-trip: model -> narrative code -> VFS -> getNarratives -> toModel
1902
1904
  it('preserves step text with multiple given events and multiple examples', async () => {
1903
1905
  const inputModel: Model = {
1904
1906
  variant: 'specs',
1905
- narratives: [
1907
+ scenes: [
1906
1908
  {
1907
1909
  name: 'Order processing',
1908
- slices: [
1910
+ moments: [
1909
1911
  {
1910
1912
  type: 'command',
1911
1913
  name: 'Complete order',
@@ -2022,14 +2024,14 @@ describe('round-trip: model -> narrative code -> VFS -> getNarratives -> toModel
2022
2024
  const generated = await modelToNarrative(inputModel);
2023
2025
 
2024
2026
  const vfs = new InMemoryFileStore();
2025
- clearGetNarrativesCache();
2027
+ clearGetScenesCache();
2026
2028
 
2027
2029
  for (const file of generated.files) {
2028
2030
  const filePath = `/project/${file.path}`;
2029
2031
  await vfs.write(filePath, new TextEncoder().encode(file.code));
2030
2032
  }
2031
2033
 
2032
- const result = await getNarratives({
2034
+ const result = await getScenes({
2033
2035
  vfs,
2034
2036
  root: '/project',
2035
2037
  pattern: /\.(narrative)\.(ts)$/,
@@ -2038,12 +2040,12 @@ describe('round-trip: model -> narrative code -> VFS -> getNarratives -> toModel
2038
2040
 
2039
2041
  const roundTrippedModel = result.toModel();
2040
2042
 
2041
- const orderNarrative = roundTrippedModel.narratives.find((n) => n.name === 'Order processing');
2042
- const completeSlice = orderNarrative!.slices.find((s) => s.name === 'Complete order');
2043
- expect(completeSlice!.type).toBe('command');
2043
+ const orderNarrative = roundTrippedModel.scenes.find((n) => n.name === 'Order processing');
2044
+ const completeMoment = orderNarrative!.moments.find((s) => s.name === 'Complete order');
2045
+ expect(completeMoment!.type).toBe('command');
2044
2046
 
2045
- if (completeSlice?.type === 'command') {
2046
- const examples = completeSlice.server.specs[0].rules[0].examples;
2047
+ if (completeMoment?.type === 'command') {
2048
+ const examples = completeMoment.server.specs[0].rules[0].examples;
2047
2049
 
2048
2050
  expect(examples[0].steps).toEqual([
2049
2051
  { keyword: 'Given', text: 'OrderCreated', docString: { orderId: 'ord_1', customerId: 'cust_1' } },
@@ -2064,14 +2066,14 @@ describe('round-trip: model -> narrative code -> VFS -> getNarratives -> toModel
2064
2066
  }
2065
2067
  });
2066
2068
 
2067
- it('preserves step text with multiple narratives in separate modules', async () => {
2069
+ it('preserves step text with multiple scenes in separate modules', async () => {
2068
2070
  const inputModel: Model = {
2069
2071
  variant: 'specs',
2070
- narratives: [
2072
+ scenes: [
2071
2073
  {
2072
2074
  name: 'Stays',
2073
2075
  sourceFile: 'stays.narrative.ts',
2074
- slices: [
2076
+ moments: [
2075
2077
  {
2076
2078
  type: 'command',
2077
2079
  name: 'Create stay',
@@ -2115,7 +2117,7 @@ describe('round-trip: model -> narrative code -> VFS -> getNarratives -> toModel
2115
2117
  {
2116
2118
  name: 'Bookings',
2117
2119
  sourceFile: 'bookings.narrative.ts',
2118
- slices: [
2120
+ moments: [
2119
2121
  {
2120
2122
  type: 'command',
2121
2123
  name: 'Book stay',
@@ -2213,7 +2215,7 @@ describe('round-trip: model -> narrative code -> VFS -> getNarratives -> toModel
2213
2215
  {
2214
2216
  sourceFile: 'stays.narrative.ts',
2215
2217
  isDerived: true,
2216
- contains: { narrativeIds: [] },
2218
+ contains: { sceneIds: [] },
2217
2219
  declares: {
2218
2220
  messages: [
2219
2221
  { kind: 'command', name: 'CreateStay' },
@@ -2224,7 +2226,7 @@ describe('round-trip: model -> narrative code -> VFS -> getNarratives -> toModel
2224
2226
  {
2225
2227
  sourceFile: 'bookings.narrative.ts',
2226
2228
  isDerived: true,
2227
- contains: { narrativeIds: [] },
2229
+ contains: { sceneIds: [] },
2228
2230
  declares: {
2229
2231
  messages: [
2230
2232
  { kind: 'event', name: 'StayPublished' },
@@ -2239,14 +2241,14 @@ describe('round-trip: model -> narrative code -> VFS -> getNarratives -> toModel
2239
2241
  const generated = await modelToNarrative(inputModel);
2240
2242
 
2241
2243
  const vfs = new InMemoryFileStore();
2242
- clearGetNarrativesCache();
2244
+ clearGetScenesCache();
2243
2245
 
2244
2246
  for (const file of generated.files) {
2245
2247
  const filePath = `/project/${file.path}`;
2246
2248
  await vfs.write(filePath, new TextEncoder().encode(file.code));
2247
2249
  }
2248
2250
 
2249
- const result = await getNarratives({
2251
+ const result = await getScenes({
2250
2252
  vfs,
2251
2253
  root: '/project',
2252
2254
  pattern: /\.(narrative)\.(ts)$/,
@@ -2255,12 +2257,12 @@ describe('round-trip: model -> narrative code -> VFS -> getNarratives -> toModel
2255
2257
 
2256
2258
  const roundTrippedModel = result.toModel();
2257
2259
 
2258
- const bookingsNarrative = roundTrippedModel.narratives.find((n) => n.name === 'Bookings');
2259
- const bookSlice = bookingsNarrative!.slices.find((s) => s.name === 'Book stay');
2260
- expect(bookSlice!.type).toBe('command');
2260
+ const bookingsNarrative = roundTrippedModel.scenes.find((n) => n.name === 'Bookings');
2261
+ const bookMoment = bookingsNarrative!.moments.find((s) => s.name === 'Book stay');
2262
+ expect(bookMoment!.type).toBe('command');
2261
2263
 
2262
- if (bookSlice?.type === 'command') {
2263
- const example = bookSlice.server.specs[0].rules[0].examples[0];
2264
+ if (bookMoment?.type === 'command') {
2265
+ const example = bookMoment.server.specs[0].rules[0].examples[0];
2264
2266
  expect(example.steps).toEqual([
2265
2267
  {
2266
2268
  keyword: 'Given',
@@ -2276,12 +2278,12 @@ describe('round-trip: model -> narrative code -> VFS -> getNarratives -> toModel
2276
2278
  ]);
2277
2279
  }
2278
2280
 
2279
- const staysNarrative = roundTrippedModel.narratives.find((n) => n.name === 'Stays');
2280
- const createSlice = staysNarrative!.slices.find((s) => s.name === 'Create stay');
2281
- expect(createSlice!.type).toBe('command');
2281
+ const staysNarrative = roundTrippedModel.scenes.find((n) => n.name === 'Stays');
2282
+ const createMoment = staysNarrative!.moments.find((s) => s.name === 'Create stay');
2283
+ expect(createMoment!.type).toBe('command');
2282
2284
 
2283
- if (createSlice?.type === 'command') {
2284
- const example = createSlice.server.specs[0].rules[0].examples[0];
2285
+ if (createMoment?.type === 'command') {
2286
+ const example = createMoment.server.specs[0].rules[0].examples[0];
2285
2287
  expect(example.steps).toEqual([
2286
2288
  { keyword: 'When', text: 'CreateStay', docString: { stayId: 'stay_1', title: 'Cozy cabin' } },
2287
2289
  { keyword: 'Then', text: 'StayCreated', docString: { stayId: 'stay_1', title: 'Cozy cabin' } },