@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,370 @@
1
+ # AI guardrails and memory
2
+
3
+ > Covers `@directive-run/ai/guardrails` and `@directive-run/ai` — input/output/toolCall guardrails (PII, prompt-injection, length, schema, content filter), memory strategies, summarizers.
4
+
5
+ Guardrails validate and transform input, output, and tool calls. Memory strategies manage conversation history with configurable summarization. Both plug into `createAgentOrchestrator` and `createMultiAgentOrchestrator`.
6
+
7
+ Import guardrail factories from the subpath barrel — the main `@directive-run/ai` re-exports them with `@deprecated` notices for v2.
8
+
9
+ ```typescript
10
+ import {
11
+ createPIIGuardrail,
12
+ createModerationGuardrail,
13
+ createRateLimitGuardrail,
14
+ createToolGuardrail,
15
+ createOutputSchemaGuardrail,
16
+ createOutputTypeGuardrail,
17
+ createLengthGuardrail,
18
+ createContentFilterGuardrail,
19
+ } from "@directive-run/ai/guardrails";
20
+ ```
21
+
22
+ ## Decision tree
23
+
24
+ ```
25
+ What are you guarding against?
26
+ ├── PII in input → createPIIGuardrail()
27
+ ├── Harmful content → createModerationGuardrail()
28
+ ├── Rate limits → createRateLimitGuardrail()
29
+ ├── Unauthorized tool calls → createToolGuardrail()
30
+ ├── Output schema mismatch → createOutputSchemaGuardrail()
31
+ ├── Output type / shape → createOutputTypeGuardrail()
32
+ ├── Response length → createLengthGuardrail()
33
+ └── Banned words/patterns → createContentFilterGuardrail()
34
+ ```
35
+
36
+ ## `GuardrailResult` shape
37
+
38
+ Every guardrail returns this shape:
39
+
40
+ ```typescript
41
+ interface GuardrailResult {
42
+ passed: boolean;
43
+ reason?: string; // populated when passed: false
44
+ transformed?: unknown; // when set, replaces the original value downstream
45
+ }
46
+ ```
47
+
48
+ When `transformed` is set, the modified value replaces the original for downstream processing — that's how redaction and sanitization work.
49
+
50
+ ## Built-in guardrails
51
+
52
+ ### PII detection + redaction
53
+
54
+ ```typescript
55
+ const piiGuardrail = createPIIGuardrail({
56
+ patterns: [/CUSTOM-\d{8}/g], // extra regex patterns beyond defaults (SSN / credit card / email)
57
+ redact: true, // redact in place instead of blocking (default: false)
58
+ redactReplacement: "***", // string to substitute (default: "[REDACTED]")
59
+ });
60
+ ```
61
+
62
+ ### Content moderation (user check function)
63
+
64
+ ```typescript
65
+ const moderation = createModerationGuardrail({
66
+ checkFn: async (text) => {
67
+ const result = await moderationAPI.check(text);
68
+ return result.flagged; // return TRUE when content should be flagged/blocked
69
+ },
70
+ message: "Content flagged by moderation", // optional override
71
+ });
72
+ ```
73
+
74
+ The check function may be sync or async. Returning `true` causes the guardrail to block.
75
+
76
+ ### Rate limiting (sliding window)
77
+
78
+ ```typescript
79
+ const rateLimit = createRateLimitGuardrail({
80
+ maxTokensPerMinute: 50_000, // default 100_000
81
+ maxRequestsPerMinute: 30, // default 60
82
+ });
83
+
84
+ // Test helper — included on the returned guardrail
85
+ rateLimit.reset();
86
+ ```
87
+
88
+ ### Tool allow/deny lists
89
+
90
+ ```typescript
91
+ const tools = createToolGuardrail({
92
+ allowlist: ["search", "calculator", "readFile"], // only these tools are allowed
93
+ denylist: ["dangerous-tool"], // any of these are blocked
94
+ caseSensitive: false, // default false
95
+ });
96
+ ```
97
+
98
+ Use `allowlist` OR `denylist` (or both). A tool not on the allowlist is blocked; a tool on the denylist is blocked.
99
+
100
+ ### Output schema validation
101
+
102
+ The validator is a function — Directive does NOT take a raw JSON schema. Use any validation library that has a `safeParse`-style API; pass an adapter.
103
+
104
+ ```typescript
105
+ import { z } from "zod";
106
+
107
+ const schemaGuardrail = createOutputSchemaGuardrail({
108
+ validate: (value) => {
109
+ const result = z.object({ title: z.string(), score: z.number() }).safeParse(value);
110
+
111
+ return {
112
+ valid: result.success,
113
+ errors: result.success ? undefined : result.error.issues.map((i) => i.message),
114
+ };
115
+ },
116
+ errorPrefix: "Output schema validation failed", // default — prepended to error.reason
117
+ });
118
+ ```
119
+
120
+ For automatic schema-retry on the agent's behalf, configure `outputSchema` + `maxSchemaRetries` on the orchestrator instead (see `ai-orchestrator.md` → Structured output).
121
+
122
+ ### Output type guard (no schema library needed)
123
+
124
+ ```typescript
125
+ const typeGuard = createOutputTypeGuardrail({
126
+ type: "object", // "string" | "number" | "boolean" | "object" | "array"
127
+ requiredFields: ["id", "name"], // object keys that must exist
128
+ minLength: 1, // for arrays
129
+ maxLength: 100, // for arrays
130
+ minStringLength: 1, // for strings
131
+ maxStringLength: 5000, // for strings
132
+ });
133
+ ```
134
+
135
+ ### Length constraints
136
+
137
+ ```typescript
138
+ const lengthGuardrail = createLengthGuardrail({
139
+ maxCharacters: 5000,
140
+ maxTokens: 1200,
141
+ estimateTokens: (text) => Math.ceil(text.length / 4), // default: chars / 4
142
+ });
143
+ ```
144
+
145
+ There is NO `minChars`, `maxChars`, or `minTokens` option — only `maxCharacters` (note the spelling) and `maxTokens`.
146
+
147
+ ### Content filter (banned patterns)
148
+
149
+ ```typescript
150
+ const contentFilter = createContentFilterGuardrail({
151
+ blockedPatterns: [/\bpassword\b/i, /\bsecret\b/i, "internal-only"],
152
+ caseSensitive: false,
153
+ });
154
+ ```
155
+
156
+ Strings are escaped and compiled to RegExp; RegExp instances pass through. There is NO `action: "redact"` mode — this guardrail blocks only. For redaction, use `createPIIGuardrail({ redact: true, patterns: [...] })`.
157
+
158
+ ## Applying guardrails
159
+
160
+ ```typescript
161
+ const orchestrator = createAgentOrchestrator({
162
+ runner,
163
+ guardrails: {
164
+ input: [piiGuardrail, rateLimit],
165
+ output: [lengthGuardrail, schemaGuardrail, contentFilter],
166
+ toolCall: [tools],
167
+ },
168
+ });
169
+ ```
170
+
171
+ ## Catching `GuardrailError`
172
+
173
+ ```typescript
174
+ import { GuardrailError, isGuardrailError } from "@directive-run/ai";
175
+
176
+ try {
177
+ await orchestrator.run(agent, prompt);
178
+ } catch (error) {
179
+ if (isGuardrailError(error)) {
180
+ console.log(error.code); // "INPUT_GUARDRAIL_FAILED" | "OUTPUT_GUARDRAIL_FAILED" | "TOOL_CALL_GUARDRAIL_FAILED" | …
181
+ console.log(error.guardrailName); // "pii-detection"
182
+ console.log(error.guardrailType); // "input" | "output" | "toolCall"
183
+ console.log(error.userMessage); // safe-to-show user-facing message
184
+ console.log(error.agentName); // which agent triggered it
185
+ // error.input and error.data are non-enumerable to prevent accidental log leakage
186
+ }
187
+ }
188
+ ```
189
+
190
+ There is no `errorCode` field — it's `code`. There is no `reason` field on `GuardrailError` — the rejection reason from the guardrail's result becomes the error's `message` (or `userMessage` for safe display).
191
+
192
+ `GuardrailErrorCode` union:
193
+ - `INPUT_GUARDRAIL_FAILED` / `OUTPUT_GUARDRAIL_FAILED` / `TOOL_CALL_GUARDRAIL_FAILED`
194
+ - `APPROVAL_REJECTED`
195
+ - `BUDGET_EXCEEDED`
196
+ - `RATE_LIMIT_EXCEEDED`
197
+ - `AGENT_ERROR`
198
+
199
+ ---
200
+
201
+ ## Memory strategies
202
+
203
+ Memory strategies control how conversation history is trimmed as it grows.
204
+
205
+ ```
206
+ How should history be trimmed?
207
+ ├── Keep N most recent messages → createSlidingWindowStrategy()
208
+ ├── Keep within token budget → createTokenBasedStrategy()
209
+ └── Both at once → createHybridStrategy()
210
+ ```
211
+
212
+ ### Sliding window (message count)
213
+
214
+ ```typescript
215
+ import { createAgentMemory, createSlidingWindowStrategy } from "@directive-run/ai";
216
+
217
+ const memory = createAgentMemory({
218
+ strategy: createSlidingWindowStrategy({
219
+ maxMessages: 50,
220
+ preserveRecentCount: 10, // always keep the N most recent (default 5)
221
+ }),
222
+ });
223
+ ```
224
+
225
+ ### Token-based
226
+
227
+ ```typescript
228
+ import { createTokenBasedStrategy } from "@directive-run/ai";
229
+
230
+ const memory = createAgentMemory({
231
+ strategy: createTokenBasedStrategy({
232
+ maxTokens: 8000,
233
+ preserveRecentCount: 5,
234
+ }),
235
+ });
236
+ ```
237
+
238
+ ### Hybrid (both constraints)
239
+
240
+ ```typescript
241
+ import { createHybridStrategy } from "@directive-run/ai";
242
+
243
+ const memory = createAgentMemory({
244
+ strategy: createHybridStrategy({
245
+ maxMessages: 100,
246
+ maxTokens: 16_000,
247
+ }),
248
+ });
249
+ ```
250
+
251
+ ## Summarizers
252
+
253
+ When messages are evicted, a summarizer condenses them.
254
+
255
+ ### Truncation (drop, no summary)
256
+
257
+ ```typescript
258
+ import { createTruncationSummarizer } from "@directive-run/ai";
259
+
260
+ const summarizer = createTruncationSummarizer();
261
+ ```
262
+
263
+ ### Key-points (rule-based, no LLM call)
264
+
265
+ ```typescript
266
+ import { createKeyPointsSummarizer } from "@directive-run/ai";
267
+
268
+ const summarizer = createKeyPointsSummarizer();
269
+ ```
270
+
271
+ ### LLM-based (async)
272
+
273
+ ```typescript
274
+ import { createLLMSummarizer } from "@directive-run/ai";
275
+
276
+ const summarizer = createLLMSummarizer(runner);
277
+ ```
278
+
279
+ ### Wiring memory to an orchestrator
280
+
281
+ ```typescript
282
+ const memory = createAgentMemory({
283
+ strategy: createSlidingWindowStrategy({ maxMessages: 50 }),
284
+ summarizer: createKeyPointsSummarizer(),
285
+ autoManage: true, // automatically trim + summarize after each run (default: true)
286
+ });
287
+
288
+ const orchestrator = createAgentOrchestrator({
289
+ runner,
290
+ memory,
291
+ });
292
+ ```
293
+
294
+ ## Anti-patterns
295
+
296
+ ### Calling guardrails by old field names
297
+
298
+ ```typescript
299
+ // WRONG — these option names don't exist
300
+ createOutputSchemaGuardrail({ schema: jsonSchema, retries: 2 }) // → use validate + outputSchema on the orchestrator for retry
301
+ createToolGuardrail({ allowedTools: [...] }) // → use allowlist
302
+ createLengthGuardrail({ minChars, maxChars, minTokens, maxTokens })// → only maxCharacters + maxTokens
303
+ createContentFilterGuardrail({ patterns, action: "redact" }) // → blockedPatterns; this guardrail BLOCKS only
304
+ ```
305
+
306
+ ### Catching `Error` instead of `GuardrailError`
307
+
308
+ ```typescript
309
+ // WRONG — loses code, guardrailName, guardrailType, userMessage
310
+ try { await orch.run(agent, prompt); } catch (e) {
311
+ if (e instanceof Error) console.log(e.message);
312
+ }
313
+
314
+ // CORRECT — narrow to GuardrailError
315
+ try { await orch.run(agent, prompt); } catch (e) {
316
+ if (e instanceof GuardrailError) {
317
+ console.log(e.code, e.guardrailName, e.userMessage);
318
+ } else {
319
+ throw e;
320
+ }
321
+ }
322
+ ```
323
+
324
+ ### Reading the wrong error fields
325
+
326
+ ```typescript
327
+ // WRONG — these don't exist on GuardrailError
328
+ error.errorCode // → use error.code
329
+ error.reason // → use error.message (or userMessage for user-facing)
330
+ ```
331
+
332
+ ### LLM summarizer with `autoManage: true`
333
+
334
+ ```typescript
335
+ // WRONG — autoManage runs synchronously; the async summarizer is never awaited
336
+ createAgentMemory({
337
+ strategy: createSlidingWindowStrategy({ maxMessages: 20 }),
338
+ summarizer: createLLMSummarizer(runner),
339
+ autoManage: true,
340
+ })
341
+
342
+ // CORRECT — disable autoManage, call memory.manage() after each run
343
+ const memory = createAgentMemory({
344
+ strategy: createSlidingWindowStrategy({ maxMessages: 20 }),
345
+ summarizer: createLLMSummarizer(runner),
346
+ autoManage: false,
347
+ });
348
+
349
+ await orchestrator.run(agent, prompt);
350
+ await memory.manage(); // awaits the async summarizer
351
+ ```
352
+
353
+ ## Quick reference
354
+
355
+ | Guardrail | Phase | Required options |
356
+ |---|---|---|
357
+ | `createPIIGuardrail` | input | (none — sensible defaults) |
358
+ | `createModerationGuardrail` | input + output | `checkFn` |
359
+ | `createRateLimitGuardrail` | input | (none — defaults 100K tokens/60 requests per minute) |
360
+ | `createToolGuardrail` | toolCall | `allowlist` or `denylist` |
361
+ | `createOutputSchemaGuardrail` | output | `validate` (`SchemaValidator<T>`) |
362
+ | `createOutputTypeGuardrail` | output | `type` |
363
+ | `createLengthGuardrail` | output | one of `maxCharacters` or `maxTokens` |
364
+ | `createContentFilterGuardrail` | output | `blockedPatterns` |
365
+
366
+ ## See also
367
+
368
+ - [`ai-orchestrator.md`](./ai-orchestrator.md) — `guardrails: { input, output, toolCall }` and `memory:` options on `createAgentOrchestrator`
369
+ - [`ai-security.md`](./ai-security.md) — `createPIIGuardrail`, `createPromptInjectionGuardrail`, `createAuditTrail`, `createCompliance` — the security-flavored guardrails
370
+ - [`ai-budget-resilience.md`](./ai-budget-resilience.md) — `createSemanticCache` pairs with `createSemanticCacheGuardrail` for caching-as-guardrail