@directive-run/claude-plugin 1.16.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 (83) hide show
  1. package/.claude-plugin/plugin.json +6 -0
  2. package/LICENSE +26 -0
  3. package/README.md +113 -0
  4. package/dist/index.cjs +2 -0
  5. package/dist/index.cjs.map +1 -0
  6. package/dist/index.d.cts +66 -0
  7. package/dist/index.d.ts +66 -0
  8. package/dist/index.js +2 -0
  9. package/dist/index.js.map +1 -0
  10. package/package.json +64 -0
  11. package/skills/README.md +9 -0
  12. package/skills/building-ai-agents/SKILL.md +414 -0
  13. package/skills/building-ai-agents/ai-adapters.md +257 -0
  14. package/skills/building-ai-agents/ai-agents-streaming.md +307 -0
  15. package/skills/building-ai-agents/ai-communication.md +304 -0
  16. package/skills/building-ai-agents/api-skeleton.md +5 -0
  17. package/skills/building-ai-agents/examples.md +849 -0
  18. package/skills/building-ai-orchestrators/SKILL.md +401 -0
  19. package/skills/building-ai-orchestrators/ai-multi-agent.md +375 -0
  20. package/skills/building-ai-orchestrators/ai-orchestrator.md +466 -0
  21. package/skills/building-ai-orchestrators/ai-tasks.md +268 -0
  22. package/skills/building-ai-orchestrators/api-skeleton.md +5 -0
  23. package/skills/building-ai-orchestrators/examples.md +1609 -0
  24. package/skills/building-directive-systems/SKILL.md +499 -0
  25. package/skills/building-directive-systems/api-skeleton.md +5 -0
  26. package/skills/building-directive-systems/examples.md +4149 -0
  27. package/skills/building-directive-systems/multi-module.md +327 -0
  28. package/skills/building-directive-systems/plugins.md +361 -0
  29. package/skills/building-directive-systems/react-adapter.md +376 -0
  30. package/skills/building-directive-systems/system-api.md +463 -0
  31. package/skills/getting-started-with-directive/SKILL.md +198 -0
  32. package/skills/getting-started-with-directive/api-skeleton.md +5 -0
  33. package/skills/getting-started-with-directive/core-patterns.md +240 -0
  34. package/skills/getting-started-with-directive/examples.md +87 -0
  35. package/skills/getting-started-with-directive/sitemap.md +202 -0
  36. package/skills/hardening-ai-systems/SKILL.md +377 -0
  37. package/skills/hardening-ai-systems/ai-budget-resilience.md +408 -0
  38. package/skills/hardening-ai-systems/ai-guardrails-memory.md +370 -0
  39. package/skills/hardening-ai-systems/ai-security.md +400 -0
  40. package/skills/hardening-ai-systems/api-skeleton.md +5 -0
  41. package/skills/hardening-ai-systems/examples.md +628 -0
  42. package/skills/migrating-to-directive/SKILL.md +249 -0
  43. package/skills/migrating-to-directive/anti-patterns.md +382 -0
  44. package/skills/migrating-to-directive/api-skeleton.md +5 -0
  45. package/skills/migrating-to-directive/core-patterns.md +240 -0
  46. package/skills/migrating-to-directive/examples.md +511 -0
  47. package/skills/migrating-to-directive/schema-types.md +273 -0
  48. package/skills/reviewing-directive-code/SKILL.md +232 -0
  49. package/skills/reviewing-directive-code/anti-patterns.md +382 -0
  50. package/skills/reviewing-directive-code/api-skeleton.md +5 -0
  51. package/skills/reviewing-directive-code/core-patterns.md +240 -0
  52. package/skills/reviewing-directive-code/examples.md +463 -0
  53. package/skills/reviewing-directive-code/naming.md +321 -0
  54. package/skills/scaffolding-directive-modules/SKILL.md +218 -0
  55. package/skills/scaffolding-directive-modules/api-skeleton.md +5 -0
  56. package/skills/scaffolding-directive-modules/core-patterns.md +240 -0
  57. package/skills/scaffolding-directive-modules/examples.md +1386 -0
  58. package/skills/scaffolding-directive-modules/naming.md +321 -0
  59. package/skills/scaffolding-directive-modules/schema-types.md +273 -0
  60. package/skills/testing-ai-systems/SKILL.md +398 -0
  61. package/skills/testing-ai-systems/ai-debug-observability.md +329 -0
  62. package/skills/testing-ai-systems/ai-mcp-rag.md +293 -0
  63. package/skills/testing-ai-systems/ai-testing-evals.md +485 -0
  64. package/skills/testing-ai-systems/api-skeleton.md +5 -0
  65. package/skills/testing-ai-systems/examples.md +1261 -0
  66. package/skills/testing-directive-code/SKILL.md +479 -0
  67. package/skills/testing-directive-code/api-skeleton.md +5 -0
  68. package/skills/testing-directive-code/examples.md +156 -0
  69. package/skills/testing-directive-code/history.md +351 -0
  70. package/skills/testing-directive-code/testing.md +412 -0
  71. package/skills/writing-directive-constraints/SKILL.md +486 -0
  72. package/skills/writing-directive-constraints/api-skeleton.md +5 -0
  73. package/skills/writing-directive-constraints/constraints.md +274 -0
  74. package/skills/writing-directive-constraints/error-boundaries.md +330 -0
  75. package/skills/writing-directive-constraints/examples.md +1361 -0
  76. package/skills/writing-directive-constraints/resolvers.md +367 -0
  77. package/skills/writing-directive-modules/SKILL.md +342 -0
  78. package/skills/writing-directive-modules/anti-patterns.md +382 -0
  79. package/skills/writing-directive-modules/api-skeleton.md +5 -0
  80. package/skills/writing-directive-modules/core-patterns.md +240 -0
  81. package/skills/writing-directive-modules/examples.md +1639 -0
  82. package/skills/writing-directive-modules/naming.md +321 -0
  83. package/skills/writing-directive-modules/schema-types.md +273 -0
@@ -0,0 +1,463 @@
1
+ # System API
2
+
3
+ > Covers `@directive-run/core` — `createSystem`, the system instance surface, hydration, inspection, distributable snapshots.
4
+
5
+ The system is created with `createSystem()` and is the runtime that orchestrates modules, constraints, resolvers, and plugins.
6
+
7
+ ## Decision Tree: "How do I interact with the system?"
8
+
9
+ ```
10
+ What do you want to do?
11
+ ├── Read/write state → system.facts.fieldName
12
+ ├── Read computed values → system.derive.derivationName
13
+ ├── Dispatch user actions → system.events.eventName(payload)
14
+ ├── React to changes → system.subscribe() or system.watch()
15
+ ├── Wait for a condition → system.when()
16
+ ├── Wait for all async to finish → system.settle()
17
+ ├── Debug/inspect current state → system.inspect()
18
+ ├── Control lifecycle → system.start() / system.stop() / system.destroy()
19
+ └── Multi-module access → system.facts.moduleName.fieldName
20
+ ```
21
+
22
+ ## Creating a System
23
+
24
+ ```typescript
25
+ import { createSystem } from "@directive-run/core";
26
+ import { loggingPlugin, devtoolsPlugin } from "@directive-run/core/plugins";
27
+
28
+ // Single module – direct access to facts/derive/events
29
+ const system = createSystem({
30
+ module: myModule,
31
+ plugins: [loggingPlugin(), devtoolsPlugin()],
32
+ history: { maxSnapshots: 100 },
33
+ });
34
+
35
+ // Multi-module – namespaced access
36
+ const system = createSystem({
37
+ modules: {
38
+ auth: authModule,
39
+ cart: cartModule,
40
+ ui: uiModule,
41
+ },
42
+ plugins: [devtoolsPlugin()],
43
+ });
44
+ ```
45
+
46
+ ## Facts: Reading and Writing State
47
+
48
+ ```typescript
49
+ // Single module
50
+ system.facts.count = 5;
51
+ const val = system.facts.count;
52
+
53
+ // Multi-module – access through module namespace
54
+ system.facts.auth.token = "abc123";
55
+ system.facts.cart.items = [];
56
+ const token = system.facts.auth.token;
57
+ ```
58
+
59
+ Facts are proxy-based. Mutations are tracked automatically and trigger derivation recomputation, constraint evaluation, and effect execution.
60
+
61
+ ## Derivations: Reading Computed Values
62
+
63
+ ```typescript
64
+ // Single module
65
+ const loading = system.derive.isLoading;
66
+ const display = system.derive.displayName;
67
+
68
+ // Multi-module
69
+ const isAdmin = system.derive.auth.isAdmin;
70
+ const total = system.derive.cart.totalPrice;
71
+ ```
72
+
73
+ Derivations are read-only. They recompute lazily when their tracked facts change.
74
+
75
+ ## Events: Dispatching Actions
76
+
77
+ ```typescript
78
+ // Single module
79
+ system.events.increment();
80
+ system.events.setUser({ user: { id: "1", name: "Alice" } });
81
+
82
+ // Multi-module
83
+ system.events.auth.login({ email: "alice@example.com" });
84
+ system.events.cart.addItem({ productId: "p1", quantity: 2 });
85
+ ```
86
+
87
+ Events are synchronous. They mutate facts in the event handler, which triggers the reactive pipeline.
88
+
89
+ ## Subscribing to Changes
90
+
91
+ ```typescript
92
+ // Subscribe to specific keys (facts or derivations)
93
+ const unsub = system.subscribe(["count", "isLoading"], () => {
94
+ console.log(system.facts.count, system.derive.isLoading);
95
+ });
96
+
97
+ // Watch a single value with old/new
98
+ system.watch("count", (newVal, oldVal) => {
99
+ console.log(`Count: ${oldVal} -> ${newVal}`);
100
+ });
101
+
102
+ // Unsubscribe
103
+ unsub();
104
+ ```
105
+
106
+ ## Waiting for Conditions
107
+
108
+ ```typescript
109
+ // Wait until a condition is true
110
+ await system.when((facts) => facts.phase === "done");
111
+
112
+ // With timeout – throws if condition not met in time
113
+ await system.when((facts) => facts.phase === "done", { timeout: 5000 });
114
+ ```
115
+
116
+ ## Settling: Waiting for Async Completion
117
+
118
+ ```typescript
119
+ system.start();
120
+
121
+ // Wait for all resolvers and async constraints to complete
122
+ await system.settle();
123
+
124
+ // With timeout
125
+ await system.settle(5000); // Throws if not settled in 5s
126
+
127
+ // Check settlement state synchronously
128
+ if (system.isSettled) {
129
+ console.log("All resolvers complete");
130
+ }
131
+
132
+ // Subscribe to settlement changes
133
+ const unsub = system.onSettledChange(() => {
134
+ console.log("Settlement:", system.isSettled);
135
+ });
136
+ ```
137
+
138
+ ## Reading by Key
139
+
140
+ ```typescript
141
+ // Read fact or derivation by string key
142
+ const count = system.read("count");
143
+ const isLoading = system.read("isLoading");
144
+
145
+ // Multi-module – use dot notation
146
+ const token = system.read("auth.token");
147
+ const total = system.read("cart.totalPrice");
148
+ ```
149
+
150
+ ## Inspecting System State
151
+
152
+ ```typescript
153
+ const inspection = system.inspect();
154
+
155
+ // Unmet requirements
156
+ inspection.unmet;
157
+ // [{ id: "req-1", requirement: { type: "FETCH_USER" }, fromConstraint: "needsUser" }]
158
+
159
+ // Inflight resolvers
160
+ inspection.inflight;
161
+ // [{ id: "req-2", resolverId: "fetchData", startedAt: 1709000000 }]
162
+
163
+ // Facts with meta
164
+ inspection.facts;
165
+ // [{ key: "userId", meta: { label: "User ID" } }, { key: "count" }]
166
+
167
+ // Constraints with state + meta
168
+ inspection.constraints;
169
+ // [{ id: "needsUser", active: true, disabled: false, priority: 0, hitCount: 3, meta: { label: "..." } }]
170
+
171
+ // Resolver definitions + meta
172
+ inspection.resolverDefs;
173
+ // [{ id: "fetchUser", requirement: "FETCH_USER", meta: { label: "..." } }]
174
+
175
+ // Resolver statuses (inflight only)
176
+ inspection.resolvers;
177
+ // { "req-1": { state: "running" } }
178
+
179
+ // Effects, derivations, modules — all with optional meta
180
+ inspection.effects; // [{ id: "log", meta: { ... } }]
181
+ inspection.derivations; // [{ id: "doubled", meta: { ... } }]
182
+ inspection.modules; // [{ id: "auth", meta: { ... } }]
183
+ inspection.events; // [{ name: "increment", meta: { ... } }]
184
+
185
+ // Unmet requirements (no matching resolver)
186
+ inspection.unmet;
187
+
188
+ // Explain why a requirement exists (uses meta.label + meta.description)
189
+ const explanation = system.explain("req-123");
190
+ ```
191
+
192
+ ## Definition Meta
193
+
194
+ Attach optional metadata to any definition for debugging, devtools, and AI context:
195
+
196
+ ```typescript
197
+ // On constraints, resolvers, effects — meta field
198
+ constraints: {
199
+ needsAuth: {
200
+ when: (f) => !f.user,
201
+ require: { type: "LOGIN" },
202
+ meta: { label: "Requires Auth", category: "auth", tags: ["critical"] },
203
+ },
204
+ },
205
+
206
+ // On derivations — { compute, meta } object form
207
+ derive: {
208
+ displayName: {
209
+ compute: (f) => `${f.first} ${f.last}`,
210
+ meta: { label: "Display Name" },
211
+ },
212
+ },
213
+
214
+ // On facts — chainable .meta()
215
+ schema: { facts: { email: t.string().meta({ label: "Email", tags: ["pii"] }) } },
216
+
217
+ // On modules
218
+ meta: { label: "Auth Module", category: "auth" },
219
+
220
+ // O(1) accessor
221
+ system.meta.constraint("needsAuth")?.label; // "Requires Auth"
222
+ system.meta.fact("email")?.tags; // ["pii"]
223
+ system.meta.module("auth")?.label; // "Auth Module"
224
+
225
+ // Bulk queries
226
+ system.meta.byCategory("auth"); // MetaMatch[] — all auth definitions
227
+ system.meta.byTag("pii"); // MetaMatch[] — all PII-tagged fields
228
+ ```
229
+
230
+ Meta is frozen at registration (Object.create(null) + Object.freeze). Zero hot-path cost. See [Definition Meta docs](https://directive.run/docs/advanced/meta).
231
+
232
+ ## Observation Protocol
233
+
234
+ Typed event stream for all lifecycle events — enables browser extensions, third-party tools, and test assertions:
235
+
236
+ ```typescript
237
+ import type { ObservationEvent } from "@directive-run/core";
238
+
239
+ const unsub = system.observe((event: ObservationEvent) => {
240
+ if (event.type === "constraint.evaluate") console.log(event.id, event.active);
241
+ if (event.type === "resolver.complete") console.log(event.resolver, event.duration);
242
+ if (event.type === "fact.change") console.log(event.key, event.prev, "→", event.next);
243
+ });
244
+
245
+ // 18 event types: fact.change, constraint.evaluate/error, requirement.created/met/canceled,
246
+ // resolver.start/complete/error, effect.run/error, derivation.compute,
247
+ // reconcile.start/end, system.init/start/stop/destroy
248
+
249
+ unsub(); // Stop observing
250
+ ```
251
+
252
+ Zero overhead when no observers. Implemented as an internal plugin.
253
+
254
+ ## Lifecycle
255
+
256
+ ```typescript
257
+ // Start – begins constraint evaluation and reconciliation
258
+ system.start();
259
+
260
+ // Stop – pauses evaluation, cancels inflight resolvers
261
+ system.stop();
262
+
263
+ // Destroy – cleans up all resources, subscriptions, plugins
264
+ system.destroy();
265
+
266
+ // Lifecycle order:
267
+ // createSystem() → system.start() → ... → system.stop() → system.destroy()
268
+ ```
269
+
270
+ `system.start()` is auto-called in most cases. Call it explicitly when you need to set up subscriptions before the first evaluation cycle.
271
+
272
+ ## Constraint Control at Runtime
273
+
274
+ ```typescript
275
+ // Disable a constraint – it won't be evaluated
276
+ system.constraints.disable("fetchWhenReady");
277
+
278
+ // Check if disabled
279
+ system.constraints.isDisabled("fetchWhenReady"); // true
280
+
281
+ // Re-enable – triggers re-evaluation on next cycle
282
+ system.constraints.enable("fetchWhenReady");
283
+ ```
284
+
285
+ ## SSR and Hydration
286
+
287
+ Four mechanisms for populating a system with external state:
288
+
289
+ ```typescript
290
+ // 1. initialFacts – simplest, at construction time
291
+ const system = createSystem({
292
+ module: myModule,
293
+ initialFacts: { userId: "user-1", name: "Alice" },
294
+ });
295
+ system.start();
296
+
297
+ // 2. system.hydrate() – async, before start()
298
+ const system = createSystem({ module: myModule });
299
+ await system.hydrate(async () => {
300
+ const res = await fetch('/api/state');
301
+
302
+ return res.json();
303
+ });
304
+ system.start();
305
+
306
+ // 3. system.restore() – sync, applies facts from a snapshot
307
+ const system = createSystem({ module: myModule });
308
+ system.restore(serverSnapshot);
309
+ system.start();
310
+
311
+ // 4. DirectiveHydrator + useHydratedSystem (React only)
312
+ // Server: getDistributableSnapshot() → serialize
313
+ // Client: <DirectiveHydrator snapshot={s}><App /></DirectiveHydrator>
314
+ // useHydratedSystem(module) inside App
315
+ ```
316
+
317
+ ### SSR Lifecycle
318
+
319
+ ```typescript
320
+ // Server: create → start → settle → snapshot → destroy
321
+ const system = createSystem({
322
+ module: pageModule,
323
+ initialFacts: { userId: req.user.id },
324
+ });
325
+ system.start();
326
+ await system.settle(5000); // Throws on timeout
327
+ const snapshot = system.getSnapshot();
328
+ system.stop();
329
+ system.destroy();
330
+ ```
331
+
332
+ ### Snapshot Types
333
+
334
+ - `SystemSnapshot` – facts only, used with `getSnapshot()` / `restore()`
335
+ - `DistributableSnapshot` – facts + derivations + metadata + TTL, used with `getDistributableSnapshot()` and `DirectiveHydrator`
336
+
337
+ ### Avoiding Singletons
338
+
339
+ Never use module-level systems in SSR – they share state across concurrent requests. Always create a fresh system per request and destroy it when done.
340
+
341
+ ## Runtime Dynamics
342
+
343
+ All four subsystems (constraints, resolvers, derivations, effects) share a uniform dynamic definition interface:
344
+
345
+ ### Enable / Disable (Constraints & Effects only)
346
+
347
+ ```typescript
348
+ system.constraints.disable("id");
349
+ system.constraints.enable("id");
350
+ system.constraints.isDisabled("id");
351
+
352
+ system.effects.disable("id");
353
+ system.effects.enable("id");
354
+ system.effects.isEnabled("id");
355
+ ```
356
+
357
+ ### Register / Assign / Unregister (All 4 subsystems)
358
+
359
+ ```typescript
360
+ // Register a new definition at runtime
361
+ system.constraints.register("id", { when: ..., require: ... });
362
+ system.resolvers.register("id", { requirement: "TYPE", resolve: ... });
363
+ system.derive.register("id", (facts) => facts.count * 3);
364
+ system.effects.register("id", { run: (facts) => { ... } });
365
+
366
+ // Override an existing definition
367
+ system.constraints.assign("id", { when: ..., require: ... });
368
+
369
+ // Remove a dynamically registered definition (static = no-op + dev warning)
370
+ system.constraints.unregister("id");
371
+ ```
372
+
373
+ Semantics: `register` throws if ID exists. `assign` throws if ID doesn't exist. `unregister` on static ID = dev warning, no-op. All three are deferred if called during reconciliation.
374
+
375
+ ### Introspection
376
+
377
+ ```typescript
378
+ system.constraints.isDynamic("id"); // true if registered at runtime
379
+ system.constraints.listDynamic(); // all dynamic constraint IDs
380
+ ```
381
+
382
+ ### getOriginal / restoreOriginal
383
+
384
+ When `assign()` overrides a static definition, the original is saved:
385
+
386
+ ```typescript
387
+ system.getOriginal("constraint", "id"); // returns original definition
388
+ system.restoreOriginal("constraint", "id"); // restores it, returns true/false
389
+ ```
390
+
391
+ ### Dynamic Module Registration
392
+
393
+ ```typescript
394
+ system.registerModule("chat", chatModule); // adds module to running system
395
+ ```
396
+
397
+ See docs: https://directive.run/docs/advanced/runtime
398
+
399
+ ## Common Mistakes
400
+
401
+ ### Reading facts before settling
402
+
403
+ ```typescript
404
+ // WRONG – resolver hasn't completed, facts are stale
405
+ system.start();
406
+ console.log(system.facts.user); // null
407
+
408
+ // CORRECT – wait for async resolution
409
+ system.start();
410
+ await system.settle();
411
+ console.log(system.facts.user); // { id: "1", name: "Alice" }
412
+ ```
413
+
414
+ ### Casting facts/derivations unnecessarily
415
+
416
+ ```typescript
417
+ // WRONG – the schema already provides types
418
+ const profile = system.facts.profile as ResourceState<Profile>;
419
+
420
+ // CORRECT – types are inferred from the schema
421
+ const profile = system.facts.profile;
422
+ ```
423
+
424
+ ### Using single-line returns without braces
425
+
426
+ ```typescript
427
+ // WRONG
428
+ system.watch("phase", (val) => { if (val === "done") return; });
429
+
430
+ // CORRECT
431
+ system.watch("phase", (val) => {
432
+ if (val === "done") {
433
+ return;
434
+ }
435
+ });
436
+ ```
437
+
438
+ ### Forgetting to destroy
439
+
440
+ ```typescript
441
+ // WRONG – resources leak
442
+ function setupSystem() {
443
+ const system = createSystem({ module: myModule });
444
+ system.start();
445
+
446
+ return system;
447
+ }
448
+
449
+ // CORRECT – clean up when done
450
+ const system = createSystem({ module: myModule });
451
+ system.start();
452
+ // ... when finished:
453
+ system.stop();
454
+ system.destroy();
455
+ ```
456
+
457
+ ## See also
458
+
459
+ - [`core-patterns.md`](./core-patterns.md) — the modules that go into `createSystem({ module: ... })`
460
+ - [`multi-module.md`](./multi-module.md) — `createSystem({ modules: { ... } })` for namespaced systems
461
+ - [`history.md`](./history.md) — the `history:` config and the `system.history.*` time-travel surface
462
+ - [`plugins.md`](./plugins.md) — the `plugins:` config and the lifecycle hooks plugins observe
463
+ - [`react-adapter.md`](./react-adapter.md) — consuming a system from React components
@@ -0,0 +1,198 @@
1
+ ---
2
+ name: getting-started-with-directive
3
+ description: "Understand Directive fundamentals: what modules, facts, derivations, constraints, resolvers, and systems are, and how they fit together. Use when someone is new to Directive, asks 'what is Directive', wants to understand the mental model, or needs help choosing between Directive concepts."
4
+ ---
5
+
6
+ # Getting Started with Directive
7
+
8
+ ## Prerequisites
9
+
10
+ This skill applies when the project uses `@directive-run/core`. If not found in `package.json`, suggest installing it: `npm install @directive-run/core`.
11
+
12
+ ## When Claude Should Use This Skill
13
+
14
+ ### Auto-Invoke Triggers
15
+ - User asks "what is Directive" or "how does Directive work"
16
+ - User is new to Directive and needs orientation
17
+ - User asks about the relationship between facts, constraints, and resolvers
18
+ - User asks "should I use a constraint or an effect" or similar conceptual questions
19
+ - User wants to understand the Directive mental model before writing code
20
+
21
+ ### Exclusions – Use a Different Skill
22
+ - User already knows Directive and wants to write a specific module → `writing-directive-modules`
23
+ - User asks about specific constraint/resolver patterns → `writing-directive-constraints`
24
+ - User asks about multi-module systems or React → `building-directive-systems`
25
+ - User asks about testing → `testing-directive-code`
26
+ - User asks about AI agents → `building-ai-orchestrators`
27
+
28
+ ---
29
+
30
+ ## Directive Mental Model
31
+
32
+ Directive is a **constraint-driven runtime** for TypeScript. Instead of imperative state management, you:
33
+
34
+ 1. **Declare facts** – observable state values
35
+ 2. **Derive** computed values – auto-tracked, no manual deps
36
+ 3. **Set constraints** – conditions that must be true (when X, require Y)
37
+ 4. **Write resolvers** – how to fulfill requirements (async handlers)
38
+ 5. **Compose into systems** – wire modules together with plugins
39
+
40
+ The runtime watches your facts, evaluates constraints, and dispatches requirements to resolvers automatically.
41
+
42
+ ## Core Concepts Flow
43
+
44
+ ```
45
+ Facts (state) → Derivations (computed)
46
+
47
+ Constraints (when/require) → Requirements → Resolvers (async handlers)
48
+
49
+ Effects (side effects, logging, sync)
50
+ ```
51
+
52
+ ## Key Terminology
53
+
54
+ | Term | What it is | Analogy |
55
+ |------|-----------|---------|
56
+ | **Fact** | A piece of observable state | Redux store field |
57
+ | **Derivation** | Auto-tracked computed value | Recoil selector |
58
+ | **Constraint** | "When X is true, require Y" declaration | Business rule |
59
+ | **Requirement** | A typed request emitted by a constraint | Redux action |
60
+ | **Resolver** | Async handler that fulfills requirements | Redux thunk |
61
+ | **Effect** | Fire-and-forget side effect on fact changes | useEffect |
62
+ | **Module** | Bundle of schema + init + derive + constraints + resolvers | Feature slice |
63
+ | **System** | Runtime that wires modules together | Redux store |
64
+
65
+ ## Minimal Example
66
+
67
+ ```typescript
68
+ import { createModule, createSystem, t } from "@directive-run/core";
69
+
70
+ const counter = createModule("counter", {
71
+ schema: {
72
+ facts: {
73
+ count: t.number(),
74
+ limit: t.number(),
75
+ },
76
+ },
77
+
78
+ init: (facts) => {
79
+ facts.count = 0;
80
+ facts.limit = 10;
81
+ },
82
+
83
+ derive: {
84
+ isAtLimit: (facts) => facts.count >= facts.limit,
85
+ remaining: (facts) => facts.limit - facts.count,
86
+ },
87
+
88
+ constraints: {
89
+ enforceLimit: {
90
+ when: (facts) => facts.count > facts.limit,
91
+ require: { type: "RESET_COUNT" },
92
+ },
93
+ },
94
+
95
+ resolvers: {
96
+ resetCount: {
97
+ requirement: "RESET_COUNT",
98
+ resolve: async (req, context) => {
99
+ context.facts.count = context.facts.limit;
100
+ },
101
+ },
102
+ },
103
+ });
104
+
105
+ const system = createSystem({ module: counter });
106
+
107
+ // Read state
108
+ console.log(system.facts.count); // 0
109
+ console.log(system.derive.isAtLimit); // false
110
+
111
+ // Mutate – constraints auto-evaluate
112
+ system.facts.count = 15;
113
+ // → constraint fires → resolver resets count to limit
114
+ ```
115
+
116
+ ## When to Use What
117
+
118
+ ```
119
+ Need to store state? → schema + init (facts)
120
+ Need computed values from state? → derive (derivations)
121
+ Need "if X then do Y" business logic? → constraint + resolver
122
+ Need side effects (logging, sync)? → effect
123
+ Need to compose multiple features? → multi-module system
124
+ Need lifecycle hooks? → plugins
125
+ ```
126
+
127
+ ## Decision Tree: Constraint vs Effect vs Direct Mutation
128
+
129
+ ```
130
+ Is it a business rule (if X then Y)?
131
+ ├── YES → Constraint + Resolver
132
+ │ Examples: auth redirect, data fetch, validation enforcement
133
+
134
+ ├── NO → Does it modify facts?
135
+ │ ├── YES → Direct mutation (system.facts.x = y)
136
+ │ │ Examples: user input, button click handlers
137
+ │ │
138
+ │ └── NO → Effect
139
+ │ Examples: logging, analytics, DOM sync, external API sync
140
+ ```
141
+
142
+ ## Common Patterns
143
+
144
+ ### Schema Type Builders
145
+
146
+ ```typescript
147
+ schema: {
148
+ facts: {
149
+ name: t.string(), // string
150
+ age: t.number(), // number
151
+ active: t.boolean(), // boolean
152
+ role: t.string<"admin" | "user">(), // union type
153
+ profile: t.object<{ name: string }>(), // typed object
154
+ tags: t.array<string>(), // typed array
155
+ data: t.object<Profile | null>(), // nullable
156
+ },
157
+ }
158
+ ```
159
+
160
+ ### Naming Convention
161
+
162
+ ```
163
+ Module name: "kebab-case" → createModule("user-auth", ...)
164
+ Fact keys: camelCase → schema: { isLoggedIn: t.boolean() }
165
+ Derivation: camelCase → derive: { canEdit: ... }
166
+ Constraint: camelCase → constraints: { enforceAuth: ... }
167
+ Resolver: camelCase → resolvers: { fetchProfile: ... }
168
+ Requirement: UPPER_SNAKE_CASE → require: { type: "FETCH_PROFILE" }
169
+ ```
170
+
171
+ ## Skill Map
172
+
173
+ All available Directive skills, grouped by use case:
174
+
175
+ **Learning:**
176
+ - `getting-started-with-directive` – This skill. Fundamentals and mental model
177
+ - `migrating-to-directive` – Convert from Redux, Zustand, XState, MobX
178
+
179
+ **Building (Core):**
180
+ - `writing-directive-modules` – Schema, type builders, derivations, naming
181
+ - `writing-directive-constraints` – Constraints, resolvers, error boundaries, retry
182
+ - `building-directive-systems` – Multi-module, plugins, React integration
183
+ - `scaffolding-directive-modules` – Generate module + test boilerplate
184
+
185
+ **Building (AI):**
186
+ - `building-ai-orchestrators` – Single and multi-agent orchestrators
187
+ - `building-ai-agents` – Streaming, provider adapters, cross-agent communication
188
+ - `hardening-ai-systems` – Guardrails, budgets, PII detection, security
189
+
190
+ **Quality:**
191
+ - `testing-directive-code` – createTestSystem, mockResolver, time-travel
192
+ - `testing-ai-systems` – Mock runners, evaluations, observability
193
+ - `reviewing-directive-code` – Anti-pattern scanner, naming audit
194
+
195
+ ## Reference Files
196
+
197
+ Supporting knowledge files loaded with this skill:
198
+ - `core-patterns.md` – Core patterns and API reference
@@ -0,0 +1,5 @@
1
+ # API Skeleton
2
+
3
+ > Auto-generated. Do not edit.
4
+
5
+ > Source JSON not found. Build website docs first.