@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,376 @@
1
+ # React Adapter
2
+
3
+ > Covers `@directive-run/react` — `useFact`, `useDerived`, `useEvents`, `useSelector`, `useDirective`, `createDirectiveContext`.
4
+
5
+ The React adapter connects Directive systems to React components. Import from `@directive-run/react`.
6
+
7
+ ## Canonical pattern: `createDirectiveContext`
8
+
9
+ This is the recommended way to use Directive in React. One call returns a typed `Provider` plus bound hooks — no system arg needed at every call site, no `useContext` boilerplate, full type inference from the schema.
10
+
11
+ ```tsx
12
+ // counter-context.ts — create once, import everywhere
13
+ import { createSystem } from "@directive-run/core";
14
+ import { createDirectiveContext } from "@directive-run/react";
15
+ import { counterModule } from "./counter-module";
16
+
17
+ export const counterSystem = createSystem({ module: counterModule });
18
+ export const Counter = createDirectiveContext(counterSystem);
19
+ ```
20
+
21
+ ```tsx
22
+ // App.tsx
23
+ import { Counter } from "./counter-context";
24
+ import { Display } from "./Display";
25
+
26
+ export function App() {
27
+ return (
28
+ <Counter.Provider>
29
+ <Display />
30
+ </Counter.Provider>
31
+ );
32
+ }
33
+ ```
34
+
35
+ ```tsx
36
+ // Display.tsx
37
+ import { Counter } from "./counter-context";
38
+
39
+ export function Display() {
40
+ const count = Counter.useFact("count");
41
+ const doubled = Counter.useDerived("doubled");
42
+ const events = Counter.useEvents();
43
+
44
+ return (
45
+ <div>
46
+ <p>Count: {count} (doubled: {doubled})</p>
47
+ <button onClick={() => events.increment()}>+1</button>
48
+ <button onClick={() => events.reset()}>Reset</button>
49
+ </div>
50
+ );
51
+ }
52
+ ```
53
+
54
+ `createDirectiveContext(system)` returns: `{ Provider, useSystem, useFact, useDerived, useEvents, useDispatch, useSelector, useWatch, useInspect, useExplain, useHistory }`. All bound to the typed system — no system argument needed when calling them.
55
+
56
+ The Provider accepts an optional `system` prop override for testing:
57
+
58
+ ```tsx
59
+ <Counter.Provider system={testSystem}>
60
+ <ComponentUnderTest />
61
+ </Counter.Provider>
62
+ ```
63
+
64
+ ## Standalone hooks (without a context)
65
+
66
+ When you don't want a context (e.g. one-off components, prototypes), import the hooks directly and pass the system to each call:
67
+
68
+ ```tsx
69
+ // system.ts
70
+ import { createSystem } from "@directive-run/core";
71
+ import { counterModule } from "./counter-module";
72
+
73
+ export const system = createSystem({ module: counterModule });
74
+ ```
75
+
76
+ ```tsx
77
+ // Counter.tsx
78
+ import { useFact, useDerived, useEvents } from "@directive-run/react";
79
+ import { system } from "./system";
80
+
81
+ export function Counter() {
82
+ const count = useFact(system, "count");
83
+ const doubled = useDerived(system, "doubled");
84
+ const events = useEvents(system);
85
+
86
+ return (
87
+ <div>
88
+ <p>Count: {count} (doubled: {doubled})</p>
89
+ <button onClick={() => events.increment()}>+1</button>
90
+ </div>
91
+ );
92
+ }
93
+ ```
94
+
95
+ ## Hook reference
96
+
97
+ ### `useFact(system, key)` or `useFact(system, [keys])`
98
+
99
+ Reads one fact (single key) or many facts (array of keys). Re-renders only when the selected fact(s) change. Return type is narrowed by the schema.
100
+
101
+ ```tsx
102
+ import { useFact } from "@directive-run/react";
103
+
104
+ function Profile() {
105
+ // Single key — typed: name is string | undefined
106
+ const name = useFact(system, "name");
107
+
108
+ // Multi-key — typed: { name: string; age: number }
109
+ const { name, age } = useFact(system, ["name", "age"]);
110
+
111
+ return <div>{name} ({age})</div>;
112
+ }
113
+ ```
114
+
115
+ ### `useDerived(system, id)` or `useDerived(system, [ids])`
116
+
117
+ Same shape as `useFact` but for derivations. Re-renders only when the derivation's value changes.
118
+
119
+ ```tsx
120
+ import { useDerived } from "@directive-run/react";
121
+
122
+ function Status() {
123
+ const isReady = useDerived(system, "isReady");
124
+ const { isReady, isLoading } = useDerived(system, ["isReady", "isLoading"]);
125
+
126
+ return <div>{isReady ? "ready" : "loading"}</div>;
127
+ }
128
+ ```
129
+
130
+ ### `useEvents(system)`
131
+
132
+ Returns the system's typed events accessor. Stable identity — does not cause re-renders. **This is the primary way to dispatch events from a component** — it carries autocomplete for every event name and payload shape.
133
+
134
+ ```tsx
135
+ import { useEvents } from "@directive-run/react";
136
+
137
+ function CartActions() {
138
+ const events = useEvents(system);
139
+
140
+ return (
141
+ <>
142
+ <button onClick={() => events.addItem({ productId: "p1" })}>Add</button>
143
+ <button onClick={() => events.checkout()}>Checkout</button>
144
+ </>
145
+ );
146
+ }
147
+
148
+ // Namespaced (multi-module) system — events are nested by module name
149
+ function Header() {
150
+ const events = useEvents(namespacedSystem);
151
+
152
+ return <button onClick={() => events.cart.addItem({ productId: "p1" })}>Add</button>;
153
+ }
154
+ ```
155
+
156
+ ### `useSelector(system, selector, equalityFn?)`
157
+
158
+ For computed values across multiple facts and derivations. Auto-tracks accessed keys; re-renders only when the selected result changes (by `Object.is` equality, override with `equalityFn`).
159
+
160
+ ```tsx
161
+ import { useSelector, shallowEqual } from "@directive-run/react";
162
+
163
+ function CheckoutSummary() {
164
+ const summary = useSelector(system, (state) => ({
165
+ itemCount: state.items.length,
166
+ total: state.cartTotal,
167
+ isReady: state.canCheckout,
168
+ }), shallowEqual);
169
+
170
+ return <div>{summary.itemCount} items · {summary.total}</div>;
171
+ }
172
+ ```
173
+
174
+ `state` carries both facts and derivations in a flat namespace — that's why it's typed `InferSelectorState<S>`, not `InferFacts<S>`.
175
+
176
+ ### `useDispatch(system)`
177
+
178
+ Returns a raw `dispatch(event)` function. Useful when you need to forward events programmatically or when the event name is computed at runtime. Prefer `useEvents` for normal dispatch — it carries typing.
179
+
180
+ ```tsx
181
+ import { useDispatch } from "@directive-run/react";
182
+
183
+ function ToolBar({ actions }: { actions: SystemEvent[] }) {
184
+ const dispatch = useDispatch(system);
185
+
186
+ return actions.map((a) => (
187
+ <button key={a.type} onClick={() => dispatch(a)}>{a.type}</button>
188
+ ));
189
+ }
190
+ ```
191
+
192
+ ### `useDirective(moduleOrOptions, selections?)`
193
+
194
+ Convenience hook that **creates a scoped system** AND selects facts/derivations in one call. The system lives for the lifetime of the component (created on mount, destroyed on unmount). Use this when the system's lifecycle should match a component's lifecycle — game boards, wizard flows, modal forms.
195
+
196
+ ```tsx
197
+ import { useDirective } from "@directive-run/react";
198
+ import { gameModule } from "./game-module";
199
+
200
+ function GameBoard() {
201
+ // Selective subscription — only re-renders when score or isOver change
202
+ const { facts: { score }, derived: { isOver }, events } = useDirective(gameModule, {
203
+ facts: ["score"],
204
+ derived: ["isOver"],
205
+ });
206
+
207
+ return (
208
+ <div>
209
+ <p>Score: {score}{isOver && " — game over!"}</p>
210
+ <button onClick={() => events.move({ direction: "up" })}>Up</button>
211
+ </div>
212
+ );
213
+ }
214
+
215
+ // Subscribe to everything (omit keys)
216
+ function Debug() {
217
+ const { facts, derived, events, dispatch } = useDirective(gameModule);
218
+
219
+ return <pre>{JSON.stringify({ facts, derived }, null, 2)}</pre>;
220
+ }
221
+ ```
222
+
223
+ For app-wide state, prefer `createDirectiveContext` over `useDirective` — the context pattern creates the system once instead of per-component.
224
+
225
+ ### `useDirectiveRef(moduleOrOptions, config?)`
226
+
227
+ Just the system-lifecycle half of `useDirective`. Returns the `SingleModuleSystem<S>` instance. Use this when you need a scoped system without consuming its state in this component (e.g., you're going to thread it through props or a context).
228
+
229
+ ### `useWatch(system, factOrDerivationId, callback)`
230
+
231
+ Imperative side-effect when a fact or derivation changes. Does NOT cause re-renders — use this for analytics, logging, focus management. For state you want to render, use `useFact` / `useDerived` / `useSelector`.
232
+
233
+ ### Status + introspection hooks
234
+
235
+ | Hook | Purpose |
236
+ |---|---|
237
+ | `useRequirementStatus(system, type)` | Reactive `idle / running / success / error` status for a requirement type |
238
+ | `useConstraintStatus(system, id)` | Reactive constraint enabled/disabled state |
239
+ | `useSuspenseRequirement(system, type)` | Same as `useRequirementStatus` but suspends until resolved (Suspense boundary required) |
240
+ | `useExplain(system, requirementId)` | Reactive English explanation of a requirement's `when` predicate |
241
+ | `useInspect(system, options?)` | Full system inspection state — constraints, requirements, resolvers, derivations |
242
+ | `useHistory(system)` | Time-travel UI helpers: `goBack`, `goForward`, `canUndo`, `canRedo`, snapshot list |
243
+ | `useAuditLedger(system)` | Subscribe to a configured `createAuditLedger` plugin's entries |
244
+
245
+ ### SSR + hydration
246
+
247
+ `DirectiveHydrator` and `useHydratedSystem` close the SSR loop. See `system-api.md` → "Hydration" for the full pattern.
248
+
249
+ ### Suspense for data fetching
250
+
251
+ `useQuerySystem` + `useSuspenseQuery` integrate `@directive-run/query`'s subscription/mutation primitives with React's Suspense and Error Boundaries. See the `@directive-run/query` docs.
252
+
253
+ ## CRITICAL: hooks that DO NOT exist
254
+
255
+ LLMs frequently hallucinate these names because they sound plausible. None of them are exported from `@directive-run/react`.
256
+
257
+ | Hallucination | Use instead |
258
+ |---|---|
259
+ | `useEvent(system)` (singular) | `useEvents(system)` (plural) |
260
+ | `useSystem(config)` as a top-level import | `useDirective(module)` or `createDirectiveContext().useSystem` |
261
+ | `DirectiveProvider` as a top-level import | `createDirectiveContext(system).Provider` |
262
+ | `useDirectiveContext()` | `createDirectiveContext(system).useSystem()` |
263
+ | `useState`-style writes like `setCount(5)` | Dispatch events: `events.setCount(5)` (or whatever your module defines) |
264
+
265
+ ```tsx
266
+ // WRONG — useEvent does not exist
267
+ import { useEvent } from "@directive-run/react";
268
+ const events = useEvent(system);
269
+
270
+ // CORRECT — useEvents (plural)
271
+ import { useEvents } from "@directive-run/react";
272
+ const events = useEvents(system);
273
+ ```
274
+
275
+ ```tsx
276
+ // WRONG — DirectiveProvider is not a top-level export
277
+ import { DirectiveProvider, useDirectiveContext } from "@directive-run/react";
278
+ <DirectiveProvider system={system}>...</DirectiveProvider>
279
+
280
+ // CORRECT — Provider comes from createDirectiveContext()
281
+ import { createDirectiveContext } from "@directive-run/react";
282
+ export const Counter = createDirectiveContext(counterSystem);
283
+ <Counter.Provider>...</Counter.Provider>
284
+ ```
285
+
286
+ ## Common mistakes
287
+
288
+ ### Creating the system inside a component body
289
+
290
+ ```tsx
291
+ // WRONG — creates a new system on every render
292
+ function Counter() {
293
+ const system = createSystem({ module: counterModule });
294
+ const count = useFact(system, "count");
295
+ return <div>{count}</div>;
296
+ }
297
+
298
+ // CORRECT — create outside the component
299
+ const system = createSystem({ module: counterModule });
300
+
301
+ function Counter() {
302
+ const count = useFact(system, "count");
303
+ return <div>{count}</div>;
304
+ }
305
+
306
+ // ALSO CORRECT — useDirective manages lifecycle
307
+ function Counter() {
308
+ const { facts: { count } } = useDirective(counterModule, { facts: ["count"] });
309
+ return <div>{count}</div>;
310
+ }
311
+ ```
312
+
313
+ ### Selecting too much state (excess re-renders)
314
+
315
+ ```tsx
316
+ // WRONG — re-renders on ANY fact change
317
+ const allFacts = useSelector(system, (s) => s);
318
+
319
+ // WRONG — re-renders even when other facts change (new object identity every time)
320
+ const profile = useSelector(system, (s) => ({ name: s.name, age: s.age }));
321
+
322
+ // CORRECT — use the targeted hook
323
+ const name = useFact(system, "name");
324
+
325
+ // CORRECT — multi-key reads a stable subset
326
+ const { name, age } = useFact(system, ["name", "age"]);
327
+
328
+ // CORRECT — useSelector with shallowEqual for shaped output
329
+ import { shallowEqual } from "@directive-run/react";
330
+ const profile = useSelector(system, (s) => ({ name: s.name, age: s.age }), shallowEqual);
331
+ ```
332
+
333
+ ### Mutating facts directly from an event handler
334
+
335
+ ```tsx
336
+ // WRONG — bypasses the event system, no audit trail, no constraint reaction
337
+ function Counter() {
338
+ const count = useFact(system, "count");
339
+ return <button onClick={() => { system.facts.count += 1; }}>{count}</button>;
340
+ }
341
+
342
+ // CORRECT — dispatch an event
343
+ function Counter() {
344
+ const count = useFact(system, "count");
345
+ const events = useEvents(system);
346
+ return <button onClick={() => events.increment()}>{count}</button>;
347
+ }
348
+ ```
349
+
350
+ ### Casting values from hooks
351
+
352
+ ```tsx
353
+ // WRONG — types come from the schema
354
+ const profile = useFact(system, "profile") as UserProfile;
355
+
356
+ // CORRECT — the schema types it for you
357
+ const profile = useFact(system, "profile");
358
+ ```
359
+
360
+ ### Forgetting `useEvents` is stable
361
+
362
+ ```tsx
363
+ // UNNECESSARY — useEvents returns a stable reference, no useCallback needed
364
+ const events = useEvents(system);
365
+ const handleClick = useCallback(() => events.increment(), [events]);
366
+
367
+ // FINE — events.increment is stable across renders too
368
+ const events = useEvents(system);
369
+ <button onClick={() => events.increment()}>+</button>
370
+ ```
371
+
372
+ ## See also
373
+
374
+ - [`system-api.md`](./system-api.md) — the system instance the hooks here read from + the SSR/hydration story
375
+ - [`core-patterns.md`](./core-patterns.md) — the module shape every React example here assumes you've built
376
+ - [`anti-patterns.md`](./anti-patterns.md) — the hallucinated React hooks (`useEvent`, `useSystem`, `DirectiveProvider`) that AI assistants reach for