@directive-run/knowledge 0.2.0 → 0.4.2

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 (54) hide show
  1. package/README.md +3 -3
  2. package/ai/ai-adapters.md +7 -7
  3. package/ai/ai-agents-streaming.md +8 -8
  4. package/ai/ai-budget-resilience.md +5 -5
  5. package/ai/ai-communication.md +1 -1
  6. package/ai/ai-guardrails-memory.md +7 -7
  7. package/ai/ai-mcp-rag.md +5 -5
  8. package/ai/ai-multi-agent.md +14 -14
  9. package/ai/ai-orchestrator.md +8 -8
  10. package/ai/ai-security.md +2 -2
  11. package/ai/ai-tasks.md +9 -9
  12. package/ai/ai-testing-evals.md +2 -2
  13. package/core/anti-patterns.md +39 -39
  14. package/core/constraints.md +15 -15
  15. package/core/core-patterns.md +9 -9
  16. package/core/error-boundaries.md +7 -7
  17. package/core/multi-module.md +16 -16
  18. package/core/naming.md +21 -21
  19. package/core/plugins.md +14 -14
  20. package/core/react-adapter.md +13 -13
  21. package/core/resolvers.md +14 -14
  22. package/core/schema-types.md +22 -22
  23. package/core/system-api.md +16 -16
  24. package/core/testing.md +5 -5
  25. package/core/time-travel.md +20 -20
  26. package/dist/index.cjs +6 -105
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.js +7 -97
  29. package/dist/index.js.map +1 -1
  30. package/examples/ab-testing.ts +18 -90
  31. package/examples/ai-checkpoint.ts +68 -87
  32. package/examples/ai-guardrails.ts +20 -70
  33. package/examples/auth-flow.ts +2 -2
  34. package/examples/batch-resolver.ts +19 -59
  35. package/examples/contact-form.ts +220 -69
  36. package/examples/counter.ts +77 -95
  37. package/examples/dashboard-loader.ts +37 -55
  38. package/examples/debounce-constraints.ts +0 -2
  39. package/examples/dynamic-modules.ts +17 -20
  40. package/examples/error-boundaries.ts +30 -81
  41. package/examples/newsletter.ts +22 -49
  42. package/examples/notifications.ts +24 -23
  43. package/examples/optimistic-updates.ts +36 -41
  44. package/examples/pagination.ts +2 -2
  45. package/examples/permissions.ts +22 -32
  46. package/examples/provider-routing.ts +26 -83
  47. package/examples/shopping-cart.ts +8 -8
  48. package/examples/sudoku.ts +55 -62
  49. package/examples/theme-locale.ts +4 -7
  50. package/examples/time-machine.ts +12 -90
  51. package/examples/topic-guard.ts +30 -38
  52. package/examples/url-sync.ts +8 -8
  53. package/examples/websocket.ts +5 -5
  54. package/package.json +3 -3
@@ -5,17 +5,17 @@
5
5
  ## 1. Unnecessary Type Casting on Facts/Derivations
6
6
 
7
7
  ```typescript
8
- // WRONG schema already provides the type
8
+ // WRONG schema already provides the type
9
9
  const profile = system.facts.profile as ResourceState<Profile>;
10
10
 
11
- // CORRECT trust the schema
11
+ // CORRECT trust the schema
12
12
  const profile = system.facts.profile;
13
13
  ```
14
14
 
15
15
  ## 2. Flat Schema (Missing facts Wrapper)
16
16
 
17
17
  ```typescript
18
- // WRONG facts must be nested under schema.facts
18
+ // WRONG facts must be nested under schema.facts
19
19
  createModule("counter", {
20
20
  schema: {
21
21
  phase: t.string(),
@@ -37,7 +37,7 @@ createModule("counter", {
37
37
  ## 3. Bare `facts.*` in Multi-Module Constraints
38
38
 
39
39
  ```typescript
40
- // WRONG multi-module constraints use facts.self for own module
40
+ // WRONG multi-module constraints use facts.self for own module
41
41
  constraints: {
42
42
  checkItems: {
43
43
  when: (facts) => facts.items.length > 0,
@@ -45,7 +45,7 @@ constraints: {
45
45
  },
46
46
  },
47
47
 
48
- // CORRECT use facts.self.* for own module facts
48
+ // CORRECT use facts.self.* for own module facts
49
49
  constraints: {
50
50
  checkItems: {
51
51
  when: (facts) => facts.self.items.length > 0,
@@ -57,7 +57,7 @@ constraints: {
57
57
  ## 4. Nonexistent Schema Builders
58
58
 
59
59
  ```typescript
60
- // WRONG t.map(), t.set(), t.promise() do not exist
60
+ // WRONG t.map(), t.set(), t.promise() do not exist
61
61
  schema: {
62
62
  facts: {
63
63
  cache: t.map<string, User>(),
@@ -66,7 +66,7 @@ schema: {
66
66
  },
67
67
  },
68
68
 
69
- // CORRECT use t.object() with type parameter
69
+ // CORRECT use t.object() with type parameter
70
70
  schema: {
71
71
  facts: {
72
72
  cache: t.object<Map<string, User>>(),
@@ -79,12 +79,12 @@ schema: {
79
79
  ## 5. Abbreviating `context` to `ctx`
80
80
 
81
81
  ```typescript
82
- // WRONG never abbreviate context
82
+ // WRONG never abbreviate context
83
83
  resolve: async (req, ctx) => {
84
84
  ctx.facts.status = "done";
85
85
  },
86
86
 
87
- // CORRECT always spell out context
87
+ // CORRECT always spell out context
88
88
  resolve: async (req, context) => {
89
89
  context.facts.status = "done";
90
90
  },
@@ -93,13 +93,13 @@ resolve: async (req, context) => {
93
93
  ## 6. Flat Module Config (No schema Wrapper)
94
94
 
95
95
  ```typescript
96
- // WRONG properties must be inside schema.facts
96
+ // WRONG properties must be inside schema.facts
97
97
  createModule("timer", {
98
98
  phase: t.string(),
99
99
  elapsed: t.number(),
100
100
  });
101
101
 
102
- // CORRECT wrap in schema: { facts: {} }
102
+ // CORRECT wrap in schema: { facts: {} }
103
103
  createModule("timer", {
104
104
  schema: {
105
105
  facts: {
@@ -113,21 +113,21 @@ createModule("timer", {
113
113
  ## 7. String-Based Event Dispatch
114
114
 
115
115
  ```typescript
116
- // WRONG events are not dispatched by string
116
+ // WRONG events are not dispatched by string
117
117
  system.dispatch("login", { token: "abc" });
118
118
 
119
- // CORRECT use the events accessor
119
+ // CORRECT use the events accessor
120
120
  system.events.login({ token: "abc" });
121
121
  ```
122
122
 
123
123
  ## 8. Direct Array/Object Mutation
124
124
 
125
125
  ```typescript
126
- // WRONG proxy cannot detect in-place mutations
126
+ // WRONG proxy cannot detect in-place mutations
127
127
  facts.items.push(item);
128
128
  facts.config.theme = "dark";
129
129
 
130
- // CORRECT replace the entire value
130
+ // CORRECT replace the entire value
131
131
  facts.items = [...facts.items, item];
132
132
  facts.config = { ...facts.config, theme: "dark" };
133
133
  ```
@@ -135,10 +135,10 @@ facts.config = { ...facts.config, theme: "dark" };
135
135
  ## 9. Nonexistent `useDirective` Hook
136
136
 
137
137
  ```typescript
138
- // WRONG there is no useDirective hook
138
+ // WRONG there is no useDirective hook
139
139
  const state = useDirective(system);
140
140
 
141
- // CORRECT use useSelector with a selector function
141
+ // CORRECT use useSelector with a selector function
142
142
  const count = useSelector(system, (s) => s.facts.count);
143
143
  const isLoading = useSelector(system, (s) => s.derive.isLoading);
144
144
  ```
@@ -146,11 +146,11 @@ const isLoading = useSelector(system, (s) => s.derive.isLoading);
146
146
  ## 10. Bracket Notation for Namespaced Facts
147
147
 
148
148
  ```typescript
149
- // WRONG internal separator is not part of the public API
149
+ // WRONG internal separator is not part of the public API
150
150
  const status = facts["auth::status"];
151
151
  const token = facts["auth_token"];
152
152
 
153
- // CORRECT use dot notation through the namespace proxy
153
+ // CORRECT use dot notation through the namespace proxy
154
154
  const status = facts.auth.status;
155
155
  const token = facts.auth.token;
156
156
  ```
@@ -158,12 +158,12 @@ const token = facts.auth.token;
158
158
  ## 11. Builder/Chaining API
159
159
 
160
160
  ```typescript
161
- // WRONG there is no builder pattern
161
+ // WRONG there is no builder pattern
162
162
  const mod = module("counter")
163
163
  .schema({ count: t.number() })
164
164
  .build();
165
165
 
166
- // CORRECT use createModule with object syntax
166
+ // CORRECT use createModule with object syntax
167
167
  const mod = createModule("counter", {
168
168
  schema: {
169
169
  facts: { count: t.number() },
@@ -174,14 +174,14 @@ const mod = createModule("counter", {
174
174
  ## 12. Returning Data from Resolvers
175
175
 
176
176
  ```typescript
177
- // WRONG resolvers return void, not data
177
+ // WRONG resolvers return void, not data
178
178
  resolve: async (req, context) => {
179
179
  const user = await fetchUser(req.userId);
180
180
 
181
181
  return user; // Return value is ignored
182
182
  },
183
183
 
184
- // CORRECT mutate context.facts to store results
184
+ // CORRECT mutate context.facts to store results
185
185
  resolve: async (req, context) => {
186
186
  const user = await fetchUser(req.userId);
187
187
  context.facts.user = user;
@@ -191,13 +191,13 @@ resolve: async (req, context) => {
191
191
  ## 13. Async Logic in `init`
192
192
 
193
193
  ```typescript
194
- // WRONG init is synchronous, facts assignment only
194
+ // WRONG init is synchronous, facts assignment only
195
195
  init: async (facts) => {
196
196
  const data = await fetch("/api/config");
197
197
  facts.config = await data.json();
198
198
  },
199
199
 
200
- // CORRECT init sets defaults; use constraints/resolvers for async work
200
+ // CORRECT init sets defaults; use constraints/resolvers for async work
201
201
  init: (facts) => {
202
202
  facts.config = null;
203
203
  facts.phase = "loading";
@@ -214,11 +214,11 @@ constraints: {
214
214
  ## 14. Missing `settle()` After `start()`
215
215
 
216
216
  ```typescript
217
- // WRONG constraints fire on start, resolvers are async
217
+ // WRONG constraints fire on start, resolvers are async
218
218
  system.start();
219
219
  console.log(system.facts.data); // May still be null
220
220
 
221
- // CORRECT wait for resolvers to complete
221
+ // CORRECT wait for resolvers to complete
222
222
  system.start();
223
223
  await system.settle();
224
224
  console.log(system.facts.data); // Resolved
@@ -227,7 +227,7 @@ console.log(system.facts.data); // Resolved
227
227
  ## 15. Missing `crossModuleDeps` Declaration
228
228
 
229
229
  ```typescript
230
- // WRONG accessing auth facts without declaring dependency
230
+ // WRONG accessing auth facts without declaring dependency
231
231
  const dataModule = createModule("data", {
232
232
  schema: { facts: { items: t.array(t.string()) } },
233
233
  constraints: {
@@ -238,7 +238,7 @@ const dataModule = createModule("data", {
238
238
  },
239
239
  });
240
240
 
241
- // CORRECT declare crossModuleDeps for type-safe cross-module access
241
+ // CORRECT declare crossModuleDeps for type-safe cross-module access
242
242
  const dataModule = createModule("data", {
243
243
  schema: { facts: { items: t.array(t.string()) } },
244
244
  crossModuleDeps: { auth: authSchema },
@@ -254,7 +254,7 @@ const dataModule = createModule("data", {
254
254
  ## 16. String Literal for `require`
255
255
 
256
256
  ```typescript
257
- // WRONG require must be an object with type property
257
+ // WRONG require must be an object with type property
258
258
  constraints: {
259
259
  check: {
260
260
  when: (facts) => facts.ready,
@@ -262,7 +262,7 @@ constraints: {
262
262
  },
263
263
  },
264
264
 
265
- // CORRECT use object form with type
265
+ // CORRECT use object form with type
266
266
  constraints: {
267
267
  check: {
268
268
  when: (facts) => facts.ready,
@@ -274,23 +274,23 @@ constraints: {
274
274
  ## 17. Passthrough Derivations
275
275
 
276
276
  ```typescript
277
- // WRONG derivation just returns a fact value unchanged
277
+ // WRONG derivation just returns a fact value unchanged
278
278
  derive: {
279
279
  count: (facts) => facts.count,
280
280
  },
281
281
 
282
- // CORRECT remove it, read the fact directly instead
282
+ // CORRECT remove it, read the fact directly instead
283
283
  // system.facts.count instead of system.derive.count
284
284
  ```
285
285
 
286
286
  ## 18. Deep Import Paths
287
287
 
288
288
  ```typescript
289
- // WRONG internal module paths are not public API
289
+ // WRONG internal module paths are not public API
290
290
  import { createModule } from "@directive-run/core/module";
291
291
  import { createSystem } from "@directive-run/core/system";
292
292
 
293
- // CORRECT import from package root
293
+ // CORRECT import from package root
294
294
  import { createModule, createSystem } from "@directive-run/core";
295
295
 
296
296
  // Exception: plugins have their own entry point
@@ -300,7 +300,7 @@ import { loggingPlugin } from "@directive-run/core/plugins";
300
300
  ## 19. Async `when()` Without `deps`
301
301
 
302
302
  ```typescript
303
- // WRONG async constraints need explicit deps for tracking
303
+ // WRONG async constraints need explicit deps for tracking
304
304
  constraints: {
305
305
  validate: {
306
306
  async: true,
@@ -313,7 +313,7 @@ constraints: {
313
313
  },
314
314
  },
315
315
 
316
- // CORRECT add deps array for async constraints
316
+ // CORRECT add deps array for async constraints
317
317
  constraints: {
318
318
  validate: {
319
319
  async: true,
@@ -331,7 +331,7 @@ constraints: {
331
331
  ## 20. No Error Handling on Failing Resolvers
332
332
 
333
333
  ```typescript
334
- // WRONG unhandled errors crash the system
334
+ // WRONG unhandled errors crash the system
335
335
  resolvers: {
336
336
  fetchData: {
337
337
  requirement: "FETCH",
@@ -342,7 +342,7 @@ resolvers: {
342
342
  },
343
343
  },
344
344
 
345
- // CORRECT use retry policy and/or module error boundary
345
+ // CORRECT use retry policy and/or module error boundary
346
346
  resolvers: {
347
347
  fetchData: {
348
348
  requirement: "FETCH",
@@ -19,10 +19,10 @@ A constraint has two parts: `when` (condition) and `require` (what's needed).
19
19
  ```typescript
20
20
  constraints: {
21
21
  fetchUserWhenReady: {
22
- // when() returns boolean evaluated on every fact change
22
+ // when() returns boolean evaluated on every fact change
23
23
  when: (facts) => facts.isAuthenticated && !facts.user,
24
24
 
25
- // require the requirement to emit when condition is true
25
+ // require the requirement to emit when condition is true
26
26
  require: { type: "FETCH_USER", userId: facts.userId },
27
27
  },
28
28
  },
@@ -31,7 +31,7 @@ constraints: {
31
31
  ### Static vs Dynamic Requirements
32
32
 
33
33
  ```typescript
34
- // Static requirement same object every time
34
+ // Static requirement same object every time
35
35
  constraints: {
36
36
  loadConfig: {
37
37
  when: (facts) => facts.config === null,
@@ -39,7 +39,7 @@ constraints: {
39
39
  },
40
40
  },
41
41
 
42
- // Dynamic requirement function that reads facts
42
+ // Dynamic requirement function that reads facts
43
43
  constraints: {
44
44
  fetchUser: {
45
45
  when: (facts) => facts.isAuthenticated && !facts.profile,
@@ -47,7 +47,7 @@ constraints: {
47
47
  },
48
48
  },
49
49
 
50
- // Multiple requirements return an array
50
+ // Multiple requirements return an array
51
51
  constraints: {
52
52
  loadAll: {
53
53
  when: (facts) => facts.phase === "init",
@@ -137,7 +137,7 @@ constraints: {
137
137
  Synchronous constraints use auto-tracking (proxy-based). Async constraints cannot be auto-tracked because the function is suspended across await boundaries. The `deps` array tells the engine which facts to watch.
138
138
 
139
139
  ```typescript
140
- // WRONG async without deps, engine cannot track dependencies
140
+ // WRONG async without deps, engine cannot track dependencies
141
141
  constraints: {
142
142
  check: {
143
143
  async: true,
@@ -146,7 +146,7 @@ constraints: {
146
146
  },
147
147
  },
148
148
 
149
- // CORRECT deps tells the engine to re-evaluate when token changes
149
+ // CORRECT deps tells the engine to re-evaluate when token changes
150
150
  constraints: {
151
151
  check: {
152
152
  async: true,
@@ -163,13 +163,13 @@ constraints: {
163
163
  const system = createSystem({ module: myModule });
164
164
  system.start();
165
165
 
166
- // Disable a constraint it won't be evaluated
166
+ // Disable a constraint it won't be evaluated
167
167
  system.constraints.disable("fetchUserWhenReady");
168
168
 
169
169
  // Check if disabled
170
170
  system.constraints.isDisabled("fetchUserWhenReady"); // true
171
171
 
172
- // Re-enable triggers re-evaluation on next cycle
172
+ // Re-enable triggers re-evaluation on next cycle
173
173
  system.constraints.enable("fetchUserWhenReady");
174
174
  ```
175
175
 
@@ -178,7 +178,7 @@ system.constraints.enable("fetchUserWhenReady");
178
178
  ### Putting async logic in resolvers instead of constraints
179
179
 
180
180
  ```typescript
181
- // WRONG resolver checks conditions (constraint's job)
181
+ // WRONG resolver checks conditions (constraint's job)
182
182
  resolvers: {
183
183
  fetchData: {
184
184
  requirement: "FETCH",
@@ -191,7 +191,7 @@ resolvers: {
191
191
  },
192
192
  },
193
193
 
194
- // CORRECT constraint declares when, resolver just does the work
194
+ // CORRECT constraint declares when, resolver just does the work
195
195
  constraints: {
196
196
  fetchWhenAuth: {
197
197
  when: (facts) => facts.isAuthenticated && !facts.data,
@@ -213,16 +213,16 @@ resolvers: {
213
213
  ### String literal for require
214
214
 
215
215
  ```typescript
216
- // WRONG require must be an object
216
+ // WRONG require must be an object
217
217
  require: "FETCH_DATA",
218
218
 
219
- // CORRECT object with type property
219
+ // CORRECT object with type property
220
220
  require: { type: "FETCH_DATA" },
221
221
 
222
- // CORRECT with payload
222
+ // CORRECT with payload
223
223
  require: { type: "FETCH_DATA", endpoint: "/api/users" },
224
224
 
225
- // CORRECT dynamic from facts
225
+ // CORRECT dynamic from facts
226
226
  require: (facts) => ({ type: "FETCH_DATA", userId: facts.currentUserId }),
227
227
  ```
228
228
 
@@ -17,7 +17,7 @@ User wants to...
17
17
  ## Module Shape (Canonical Object Syntax)
18
18
 
19
19
  ```typescript
20
- // CORRECT full module definition
20
+ // CORRECT full module definition
21
21
  import { createModule, t } from "@directive-run/core";
22
22
 
23
23
  const myModule = createModule("name", {
@@ -104,14 +104,14 @@ const myModule = createModule("name", {
104
104
  import { createSystem } from "@directive-run/core";
105
105
  import { loggingPlugin, devtoolsPlugin } from "@directive-run/core/plugins";
106
106
 
107
- // Single module direct access: system.facts.count
107
+ // Single module direct access: system.facts.count
108
108
  const system = createSystem({
109
109
  module: myModule,
110
110
  plugins: [loggingPlugin(), devtoolsPlugin()],
111
111
  debug: { timeTravel: true, maxSnapshots: 100 },
112
112
  });
113
113
 
114
- // Multi-module namespaced access: system.facts.auth.token
114
+ // Multi-module namespaced access: system.facts.auth.token
115
115
  const system = createSystem({
116
116
  modules: { auth: authModule, cart: cartModule },
117
117
  plugins: [devtoolsPlugin()],
@@ -130,7 +130,7 @@ system.destroy();
130
130
  WRONG thinking: "I'll put the fetch call in a resolver that checks auth."
131
131
 
132
132
  ```typescript
133
- // WRONG resolver doing condition checking + data fetching
133
+ // WRONG resolver doing condition checking + data fetching
134
134
  resolvers: {
135
135
  fetchData: {
136
136
  requirement: "FETCH_DATA",
@@ -148,7 +148,7 @@ resolvers: {
148
148
  CORRECT thinking: "Constraint declares WHEN, resolver declares HOW."
149
149
 
150
150
  ```typescript
151
- // CORRECT constraint declares the need, resolver fulfills it
151
+ // CORRECT constraint declares the need, resolver fulfills it
152
152
  constraints: {
153
153
  fetchWhenAuthenticated: {
154
154
  when: (facts) => facts.isAuthenticated && !facts.data,
@@ -170,14 +170,14 @@ resolvers: {
170
170
  ## Reading System State
171
171
 
172
172
  ```typescript
173
- // Facts mutable state
173
+ // Facts mutable state
174
174
  system.facts.count = 5;
175
175
  const val = system.facts.count;
176
176
 
177
- // Derivations read-only computed values
177
+ // Derivations read-only computed values
178
178
  const loading = system.derive.isLoading;
179
179
 
180
- // Events dispatch user actions
180
+ // Events dispatch user actions
181
181
  system.events.increment();
182
182
  system.events.setUser({ user: { id: "1", name: "Alice" } });
183
183
 
@@ -201,7 +201,7 @@ await system.when((facts) => facts.phase === "done", { timeout: 5000 });
201
201
  Only `facts` is required in the schema. Other sections are optional:
202
202
 
203
203
  ```typescript
204
- // Minimal module facts only
204
+ // Minimal module facts only
205
205
  const minimal = createModule("minimal", {
206
206
  schema: {
207
207
  facts: { count: t.number() },
@@ -53,7 +53,7 @@ const system = createSystem({
53
53
  onEffectError: "skip",
54
54
  onDerivationError: "throw",
55
55
 
56
- // Global error callback fires for all errors
56
+ // Global error callback fires for all errors
57
57
  onError: (error) => {
58
58
  // error is a DirectiveError with source tracking
59
59
  console.error(`[${error.source}] ${error.sourceId}: ${error.message}`);
@@ -79,17 +79,17 @@ Use functions instead of strings for conditional recovery:
79
79
  ```typescript
80
80
  errorBoundary: {
81
81
  onResolverError: (error, resolverId) => {
82
- // Network errors retry later
82
+ // Network errors retry later
83
83
  if (error.message.includes("NetworkError")) {
84
84
  return "retry-later";
85
85
  }
86
86
 
87
- // Auth errors skip, don't retry
87
+ // Auth errors skip, don't retry
88
88
  if (error.message.includes("401")) {
89
89
  return "skip";
90
90
  }
91
91
 
92
- // Everything else throw
92
+ // Everything else throw
93
93
  return "throw";
94
94
  },
95
95
 
@@ -125,8 +125,8 @@ try {
125
125
  } catch (err) {
126
126
  if (err instanceof DirectiveError) {
127
127
  err.source; // "constraint" | "resolver" | "effect" | "derivation" | "system"
128
- err.sourceId; // e.g., "fetchUser" the specific item that failed
129
- err.recoverable; // boolean whether recovery strategies apply
128
+ err.sourceId; // e.g., "fetchUser" the specific item that failed
129
+ err.recoverable; // boolean whether recovery strategies apply
130
130
  err.context; // arbitrary debug data (e.g., the requirement object)
131
131
  err.message; // human-readable description
132
132
  }
@@ -286,7 +286,7 @@ HALF_OPEN → Limited trial requests allowed
286
286
 
287
287
  ```typescript
288
288
  apiBreaker.getState(); // "CLOSED" | "OPEN" | "HALF_OPEN"
289
- apiBreaker.isAllowed(); // boolean would a request be allowed?
289
+ apiBreaker.isAllowed(); // boolean would a request be allowed?
290
290
  apiBreaker.getStats(); // { totalRequests, totalFailures, recentFailures, ... }
291
291
  apiBreaker.forceState("CLOSED"); // Force state (useful in tests)
292
292
  apiBreaker.reset(); // Reset to CLOSED with cleared stats
@@ -68,7 +68,7 @@ const cartModule = createModule("cart", {
68
68
  },
69
69
  });
70
70
 
71
- // Multi-module system namespaced access
71
+ // Multi-module system namespaced access
72
72
  const system = createSystem({
73
73
  modules: { auth: authModule, cart: cartModule },
74
74
  });
@@ -79,24 +79,24 @@ system.start();
79
79
  ## Accessing Namespaced State
80
80
 
81
81
  ```typescript
82
- // Facts namespaced under module name
82
+ // Facts namespaced under module name
83
83
  system.facts.auth.token;
84
84
  system.facts.auth.isAuthenticated;
85
85
  system.facts.cart.items;
86
86
 
87
- // Derivations namespaced under module name
87
+ // Derivations namespaced under module name
88
88
  system.derive.cart.itemCount;
89
89
 
90
- // Events namespaced under module name
90
+ // Events namespaced under module name
91
91
  system.events.auth.login({ token: "abc123" });
92
92
  system.events.auth.logout();
93
93
 
94
- // Subscribe use "namespace.key" format
94
+ // Subscribe use "namespace.key" format
95
95
  system.subscribe(["auth.token", "cart.items"], () => {
96
96
  console.log("auth or cart changed");
97
97
  });
98
98
 
99
- // Watch use "namespace.key" format
99
+ // Watch use "namespace.key" format
100
100
  system.watch("auth.isAuthenticated", (newVal, oldVal) => {
101
101
  console.log(`Auth: ${oldVal} -> ${newVal}`);
102
102
  });
@@ -106,7 +106,7 @@ system.subscribeModule("cart", () => {
106
106
  console.log("anything in cart changed");
107
107
  });
108
108
 
109
- // Wait for condition facts are namespaced
109
+ // Wait for condition facts are namespaced
110
110
  await system.when((facts) => facts.auth.isAuthenticated);
111
111
  ```
112
112
 
@@ -166,7 +166,7 @@ const dataModule = createModule("data", {
166
166
  facts.loaded = false;
167
167
  },
168
168
 
169
- // CORRECT facts.self for own module, facts.auth for cross-module
169
+ // CORRECT facts.self for own module, facts.auth for cross-module
170
170
  constraints: {
171
171
  fetchWhenAuth: {
172
172
  when: (facts) => facts.auth.isAuthenticated && !facts.self.loaded,
@@ -203,7 +203,7 @@ const dataModule = createModule("data", {
203
203
  ### Using bare `facts.*` instead of `facts.self.*`
204
204
 
205
205
  ```typescript
206
- // WRONG in cross-module context, bare facts has no self-module properties
206
+ // WRONG in cross-module context, bare facts has no self-module properties
207
207
  constraints: {
208
208
  check: {
209
209
  when: (facts) => facts.loaded, // TypeScript error
@@ -211,7 +211,7 @@ constraints: {
211
211
  },
212
212
  },
213
213
 
214
- // CORRECT use facts.self for own module
214
+ // CORRECT use facts.self for own module
215
215
  constraints: {
216
216
  check: {
217
217
  when: (facts) => facts.self.loaded,
@@ -223,11 +223,11 @@ constraints: {
223
223
  ### Bracket notation for internal keys
224
224
 
225
225
  ```typescript
226
- // WRONG the :: separator is internal, never use it directly
226
+ // WRONG the :: separator is internal, never use it directly
227
227
  system.facts["auth::token"];
228
228
  system.read("auth::status");
229
229
 
230
- // CORRECT dot notation through namespace proxy
230
+ // CORRECT dot notation through namespace proxy
231
231
  system.facts.auth.token;
232
232
  system.read("auth.status");
233
233
  ```
@@ -235,7 +235,7 @@ system.read("auth.status");
235
235
  ### Forgetting crossModuleDeps
236
236
 
237
237
  ```typescript
238
- // WRONG facts.auth is untyped without crossModuleDeps
238
+ // WRONG facts.auth is untyped without crossModuleDeps
239
239
  const dataModule = createModule("data", {
240
240
  schema: { facts: { items: t.array(t.string()) } },
241
241
  constraints: {
@@ -246,7 +246,7 @@ const dataModule = createModule("data", {
246
246
  },
247
247
  });
248
248
 
249
- // CORRECT declare the dependency
249
+ // CORRECT declare the dependency
250
250
  const dataModule = createModule("data", {
251
251
  schema: { facts: { items: t.array(t.string()) } },
252
252
  crossModuleDeps: { auth: authSchema },
@@ -265,13 +265,13 @@ const dataModule = createModule("data", {
265
265
  const system = createSystem({
266
266
  modules: { auth: authModule, cart: cartModule, data: dataModule },
267
267
 
268
- // Initial facts applied after init(), before first reconciliation
268
+ // Initial facts applied after init(), before first reconciliation
269
269
  initialFacts: {
270
270
  auth: { token: "restored-token" },
271
271
  cart: { items: cachedItems },
272
272
  },
273
273
 
274
- // Init order control module initialization sequence
274
+ // Init order control module initialization sequence
275
275
  initOrder: "auto", // Sort by crossModuleDeps topology (default)
276
276
  // initOrder: "declaration", // Use object key order
277
277
  // initOrder: ["auth", "data", "cart"], // Explicit order