@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,499 @@
1
+ ---
2
+ name: building-directive-systems
3
+ description: "Compose Directive modules into systems: single-module and multi-module createSystem() calls, namespaced fact/derive/event access, cross-module dependencies, initialFacts and hydration, plugins (logging, devtools, persistence, circuit breaker), React adapter hooks (useSelector, useEvent, useSystem, DirectiveProvider), and system lifecycle. Use when creating a system, connecting modules together, adding plugins, or integrating Directive with React."
4
+ ---
5
+
6
+ # Building Directive Systems
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 when the user:**
15
+ - Says "create a system", "compose modules", "add plugins", or "connect to React"
16
+ - Shows `createSystem()` and asks to extend it with more modules or plugins
17
+ - Asks about `useSelector`, `useEvent`, `useSystem`, or `DirectiveProvider`
18
+ - Asks how modules share state or read each other's facts
19
+ - Asks about system lifecycle, hydration, or dynamic module registration
20
+
21
+ **Do NOT invoke when:**
22
+ - Writing a module for the first time (start with `writing-directive-modules.md`)
23
+ - Writing constraints/resolvers only (see `writing-directive-constraints.md`)
24
+ - Writing tests (see `testing-directive-code.md`)
25
+
26
+ ---
27
+
28
+ ## Decision Tree: Single or Multi-Module?
29
+
30
+ ```
31
+ How many state domains?
32
+ ├── One → createSystem({ module: myModule })
33
+ │ Direct access: system.facts.count
34
+
35
+ └── Two or more → createSystem({ modules: { auth, cart, ui } })
36
+ Namespaced: system.facts.auth.token
37
+
38
+ Does module A need to read module B's state in constraints/effects/derivations?
39
+ ├── No → No crossModuleDeps needed
40
+ └── Yes → Declare crossModuleDeps on the consuming module
41
+ Own facts at facts.self.*, other module at facts.otherModule.*
42
+ ```
43
+
44
+ ---
45
+
46
+ ## System Creation
47
+
48
+ ### Single module
49
+
50
+ ```typescript
51
+ import { createSystem } from "@directive-run/core";
52
+ import { loggingPlugin, devtoolsPlugin } from "@directive-run/core/plugins";
53
+
54
+ const system = createSystem({
55
+ module: myModule,
56
+ plugins: [loggingPlugin(), devtoolsPlugin()],
57
+ history: { maxSnapshots: 100 },
58
+ });
59
+
60
+ system.start();
61
+ await system.settle(); // Wait for all resolvers to complete
62
+ ```
63
+
64
+ ### Multi-module
65
+
66
+ ```typescript
67
+ const system = createSystem({
68
+ modules: { auth: authModule, cart: cartModule, data: dataModule },
69
+ plugins: [loggingPlugin(), devtoolsPlugin()],
70
+ initialFacts: {
71
+ auth: { token: "restored-token" },
72
+ cart: { items: [] },
73
+ },
74
+ initOrder: "auto", // "auto" | "declaration" | ["auth", "data", "cart"]
75
+ });
76
+
77
+ system.start();
78
+ await system.settle();
79
+ ```
80
+
81
+ ### Hydration from async source (before start)
82
+
83
+ ```typescript
84
+ await system.hydrate(async () => {
85
+ const stored = localStorage.getItem("app-state");
86
+
87
+ return stored ? JSON.parse(stored) : {};
88
+ });
89
+
90
+ system.start();
91
+ ```
92
+
93
+ ### Dynamic module registration at runtime
94
+
95
+ ```typescript
96
+ const chatModule = await import("./modules/chat");
97
+ system.registerModule("chat", chatModule.default);
98
+ // Now: system.facts.chat.*, system.events.chat.*, etc.
99
+ ```
100
+
101
+ ---
102
+
103
+ ## Accessing System State
104
+
105
+ ### Single module – direct access
106
+
107
+ ```typescript
108
+ system.facts.count = 5;
109
+ const val = system.facts.count;
110
+ const loading = system.derive.isLoading;
111
+ system.events.increment();
112
+ system.events.setUser({ user: { id: "1", name: "Alice" } });
113
+ ```
114
+
115
+ ### Multi-module – namespaced access (dot notation always)
116
+
117
+ ```typescript
118
+ system.facts.auth.token;
119
+ system.facts.cart.items;
120
+ system.derive.auth.isAdmin;
121
+ system.derive.cart.itemCount;
122
+ system.events.auth.login({ token: "abc" });
123
+ system.events.cart.addItem({ productId: "p1", qty: 1 });
124
+ ```
125
+
126
+ ```typescript
127
+ // WRONG – internal separator never used in public API
128
+ system.facts["auth::token"];
129
+ system.facts["auth_token"];
130
+
131
+ // CORRECT – dot notation through namespace proxy
132
+ system.facts.auth.token;
133
+ ```
134
+
135
+ ### Subscribing and watching
136
+
137
+ ```typescript
138
+ // Subscribe to multiple keys
139
+ const unsub = system.subscribe(["count", "isLoading"], () => {
140
+ console.log(system.facts.count, system.derive.isLoading);
141
+ });
142
+
143
+ // Multi-module keys use "module.key" format
144
+ system.subscribe(["auth.token", "cart.items"], () => { ... });
145
+
146
+ // Watch a single value with old/new
147
+ system.watch("count", (newVal, oldVal) => {
148
+ console.log(`Count: ${oldVal} -> ${newVal}`);
149
+ });
150
+
151
+ // Subscribe to all keys in a module
152
+ system.subscribeModule("cart", () => { ... });
153
+
154
+ // Wait for condition
155
+ await system.when((facts) => facts.phase === "done");
156
+ await system.when((facts) => facts.auth.isAuthenticated, { timeout: 5000 });
157
+ ```
158
+
159
+ ### System lifecycle
160
+
161
+ ```typescript
162
+ system.start(); // Begins constraint evaluation and reconciliation
163
+ system.stop(); // Pauses evaluation, cancels inflight resolvers
164
+ system.destroy(); // Full cleanup – subscriptions, plugins, resources
165
+ ```
166
+
167
+ Always call `destroy()` when a system is no longer needed (teardown, React unmount, test cleanup).
168
+
169
+ ---
170
+
171
+ ## Cross-Module Dependencies
172
+
173
+ Export the schema separately so other modules can reference it for type safety.
174
+
175
+ ```typescript
176
+ // modules/auth.ts
177
+ export const authSchema = {
178
+ facts: {
179
+ token: t.string<string | null>(),
180
+ isAuthenticated: t.boolean(),
181
+ },
182
+ } as const;
183
+
184
+ export const authModule = createModule("auth", {
185
+ schema: authSchema,
186
+ init: (facts) => {
187
+ facts.token = null;
188
+ facts.isAuthenticated = false;
189
+ },
190
+ events: {
191
+ login: (facts, payload) => { facts.token = payload.token; facts.isAuthenticated = true; },
192
+ logout: (facts) => { facts.token = null; facts.isAuthenticated = false; },
193
+ },
194
+ });
195
+ ```
196
+
197
+ ```typescript
198
+ // modules/data.ts
199
+ import { authSchema } from "./auth";
200
+
201
+ const dataModule = createModule("data", {
202
+ schema: { facts: { items: t.array(t.string()), loaded: t.boolean() } },
203
+ crossModuleDeps: { auth: authSchema },
204
+ init: (facts) => { facts.items = []; facts.loaded = false; },
205
+
206
+ constraints: {
207
+ fetchWhenAuth: {
208
+ when: (facts) => facts.auth.isAuthenticated && !facts.self.loaded,
209
+ require: { type: "FETCH_ITEMS" },
210
+ },
211
+ },
212
+
213
+ effects: {
214
+ onAuthChange: {
215
+ run: (facts, prev) => {
216
+ if (prev && prev.auth.isAuthenticated && !facts.auth.isAuthenticated) {
217
+ console.log("User logged out");
218
+ }
219
+ },
220
+ },
221
+ },
222
+ });
223
+ ```
224
+
225
+ ---
226
+
227
+ ## Plugins
228
+
229
+ ### Built-in plugins
230
+
231
+ ```typescript
232
+ import {
233
+ loggingPlugin,
234
+ devtoolsPlugin,
235
+ persistencePlugin,
236
+ } from "@directive-run/core/plugins";
237
+
238
+ const plugins = [];
239
+
240
+ if (process.env.NODE_ENV === "development") {
241
+ plugins.push(loggingPlugin({ verbose: true })); // Logging first
242
+ plugins.push(devtoolsPlugin({ name: "My App" }));
243
+ }
244
+
245
+ plugins.push(persistencePlugin({
246
+ key: "app-state",
247
+ storage: localStorage,
248
+ exclude: ["authToken", "isLoading"], // Skip sensitive/transient
249
+ version: 1,
250
+ migrate: (old, version) => old, // Always version when persisting
251
+ }));
252
+ ```
253
+
254
+ Plugin order matters – logging first captures all events including those from other plugins.
255
+
256
+ ### Custom plugin
257
+
258
+ ```typescript
259
+ import type { DirectivePlugin } from "@directive-run/core";
260
+
261
+ const myPlugin: DirectivePlugin = {
262
+ name: "my-plugin",
263
+ onInit: (system) => { ... },
264
+ onStart: (system) => { ... },
265
+ onStop: (system) => { ... },
266
+ onSnapshot: (snapshot) => {
267
+ // snapshot.facts, snapshot.changedKeys
268
+ },
269
+ onRequirementEmitted: (requirement) => { ... },
270
+ onResolutionStart: (resolution) => { ... },
271
+ onResolutionComplete: (resolution) => { ... },
272
+ onError: (error, context) => { ... },
273
+ };
274
+ ```
275
+
276
+ ---
277
+
278
+ ## React Adapter
279
+
280
+ Import from `@directive-run/react`.
281
+
282
+ ### Setup: create system outside React
283
+
284
+ ```typescript
285
+ // system.ts – created once, imported anywhere
286
+ export const system = createSystem({ module: counterModule });
287
+ ```
288
+
289
+ ### useSelector – subscribe to state
290
+
291
+ Re-renders only when the selected value changes (shallow comparison).
292
+
293
+ ```typescript
294
+ import { useSelector, useEvent } from "@directive-run/react";
295
+
296
+ function Counter() {
297
+ const count = useSelector(system, (s) => s.facts.count);
298
+ const doubled = useSelector(system, (s) => s.derive.doubled);
299
+
300
+ // Multi-module
301
+ const token = useSelector(system, (s) => s.facts.auth.token);
302
+ const itemCount = useSelector(system, (s) => s.derive.cart.itemCount);
303
+
304
+ const events = useEvent(system);
305
+
306
+ return (
307
+ <div>
308
+ <p>Count: {count}</p>
309
+ <button onClick={() => events.increment()}>+1</button>
310
+ </div>
311
+ );
312
+ }
313
+ ```
314
+
315
+ ### useEvent – dispatch events (stable reference)
316
+
317
+ ```typescript
318
+ const events = useEvent(system);
319
+ events.increment();
320
+ events.auth.login({ token: "abc" }); // Multi-module
321
+ ```
322
+
323
+ ### useSystem – lifecycle scoped to component
324
+
325
+ ```typescript
326
+ import { useSystem } from "@directive-run/react";
327
+
328
+ function GameBoard() {
329
+ const gameSystem = useSystem({ // Created on mount, destroyed on unmount
330
+ module: gameModule,
331
+ history: true,
332
+ });
333
+ const score = useSelector(gameSystem, (s) => s.facts.score);
334
+
335
+ return <div>Score: {score}</div>;
336
+ }
337
+ ```
338
+
339
+ Use `useSystem` when the system's lifecycle matches a component's lifecycle (wizard, game board, modal form). For app-wide state, create outside React.
340
+
341
+ ### DirectiveProvider – share system via context
342
+
343
+ ```typescript
344
+ import { DirectiveProvider, useDirectiveContext } from "@directive-run/react";
345
+
346
+ function App() {
347
+ return (
348
+ <DirectiveProvider system={system}>
349
+ <Dashboard />
350
+ </DirectiveProvider>
351
+ );
352
+ }
353
+
354
+ function Dashboard() {
355
+ const system = useDirectiveContext();
356
+ const stats = useSelector(system, (s) => s.derive.dashboardStats);
357
+
358
+ return <div>{stats.totalUsers} users</div>;
359
+ }
360
+ ```
361
+
362
+ ---
363
+
364
+ ## Critical Anti-Patterns
365
+
366
+ ### 1. Reading facts before settling
367
+
368
+ ```typescript
369
+ // WRONG – resolver hasn't completed
370
+ system.start();
371
+ console.log(system.facts.user); // null
372
+
373
+ // CORRECT
374
+ system.start();
375
+ await system.settle();
376
+ console.log(system.facts.user); // resolved
377
+ ```
378
+
379
+ ### 2. Forgetting to start the system
380
+
381
+ ```typescript
382
+ // WRONG – constraints never evaluate
383
+ const system = createSystem({ module: myModule });
384
+ console.log(system.facts.phase); // "idle" – resolvers never ran
385
+
386
+ // CORRECT
387
+ system.start();
388
+ await system.settle();
389
+ ```
390
+
391
+ ### 3. Missing crossModuleDeps
392
+
393
+ ```typescript
394
+ // WRONG – facts.auth untyped, no reactive tracking
395
+ when: (facts) => facts.auth.isAuthenticated, // TypeScript error
396
+
397
+ // CORRECT
398
+ crossModuleDeps: { auth: authSchema },
399
+ when: (facts) => facts.auth.isAuthenticated, // Fully typed + tracked
400
+ ```
401
+
402
+ ### 4. Bare facts.* in cross-module context
403
+
404
+ ```typescript
405
+ // WRONG – in cross-module constraints, bare facts has no self properties
406
+ when: (facts) => facts.loaded,
407
+
408
+ // CORRECT
409
+ when: (facts) => facts.self.loaded,
410
+ ```
411
+
412
+ ### 5. Bracket notation for namespaced access
413
+
414
+ ```typescript
415
+ // WRONG
416
+ system.facts["auth::token"];
417
+
418
+ // CORRECT
419
+ system.facts.auth.token;
420
+ ```
421
+
422
+ ### 6. Creating system inside a React component without useSystem
423
+
424
+ ```typescript
425
+ // WRONG – new system on every render
426
+ function Counter() {
427
+ const system = createSystem({ module: counterModule }); // Bug!
428
+ }
429
+
430
+ // CORRECT – module-level or useSystem()
431
+ const system = createSystem({ module: counterModule });
432
+ ```
433
+
434
+ ### 7. The nonexistent useDirective hook
435
+
436
+ ```typescript
437
+ // WRONG – this does not exist
438
+ const { facts, derive, events } = useDirective(system);
439
+
440
+ // CORRECT
441
+ const count = useSelector(system, (s) => s.facts.count);
442
+ const events = useEvent(system);
443
+ ```
444
+
445
+ ### 8. Selecting too much state in useSelector
446
+
447
+ ```typescript
448
+ // WRONG – re-renders on any fact change
449
+ const allFacts = useSelector(system, (s) => s.facts);
450
+
451
+ // CORRECT – select only what you need
452
+ const name = useSelector(system, (s) => s.facts.userName);
453
+ ```
454
+
455
+ ### 9. devtoolsPlugin in production
456
+
457
+ ```typescript
458
+ // CORRECT – gate on environment
459
+ const plugins = process.env.NODE_ENV === "development"
460
+ ? [loggingPlugin(), devtoolsPlugin()]
461
+ : [];
462
+ ```
463
+
464
+ ### 10. persistencePlugin without version
465
+
466
+ ```typescript
467
+ // WRONG – schema changes break existing users
468
+ persistencePlugin({ key: "app", storage: localStorage })
469
+
470
+ // CORRECT
471
+ persistencePlugin({ key: "app", storage: localStorage, version: 1, migrate: (old) => old })
472
+ ```
473
+
474
+ ---
475
+
476
+ ## Inspecting System State
477
+
478
+ ```typescript
479
+ const inspection = system.inspect();
480
+ inspection.facts; // Current fact snapshot
481
+ inspection.derivations; // Derivation values
482
+ inspection.requirements; // Active requirements
483
+ inspection.constraintDefs; // Constraint definitions and state
484
+ inspection.resolvers; // Resolver statuses
485
+ inspection.inflight; // Currently running resolvers
486
+ inspection.unmet; // Requirements with no matching resolver
487
+
488
+ system.explain("req-123"); // Why this requirement exists
489
+ system.isSettled; // boolean
490
+ ```
491
+
492
+ ---
493
+
494
+ ## Reference Files
495
+
496
+ - `multi-module.md` – crossModuleDeps, module schema export pattern, subscribe/watch in multi-module
497
+ - `system-api.md` – full system API reference, read(), watch(), when(), lifecycle order
498
+ - `plugins.md` – all built-in plugins with full config, custom plugin lifecycle hooks
499
+ - `react-adapter.md` – all React hooks with examples, common mistakes, multi-module patterns
@@ -0,0 +1,5 @@
1
+ # API Skeleton
2
+
3
+ > Auto-generated. Do not edit.
4
+
5
+ > Source JSON not found. Build website docs first.