@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,377 @@
1
+ ---
2
+ name: hardening-ai-systems
3
+ description: "Add guardrails (input/output validation), memory strategies, token budgets, PII detection, prompt injection prevention, and circuit breakers to AI orchestrators. Use when enforcing content policies, managing costs, preventing security vulnerabilities, adding resilience, or implementing agent memory across turns."
4
+ ---
5
+
6
+ # Hardening AI Systems
7
+
8
+ ## Prerequisites
9
+
10
+ This skill applies when the project uses `@directive-run/ai`. If not found in `package.json`, suggest installing it: `npm install @directive-run/ai`.
11
+
12
+ ## When Claude Should Use This Skill
13
+
14
+ ## Auto-Invoke Triggers
15
+ - User asks about input/output validation for LLM calls
16
+ - User wants to prevent harmful content or prompt injection
17
+ - User needs to control token spending or set cost limits
18
+ - User asks about agent memory, conversation history, or context management
19
+ - User mentions `createGuardrail`, `GuardrailError`, `createAgentMemory`
20
+ - User wants retry logic, circuit breakers, or failure resilience
21
+
22
+ ## Exclusions
23
+ - Do NOT invoke for basic orchestrator/agent setup – use `building-ai-orchestrators`
24
+ - Do NOT invoke for streaming or provider setup – use `building-ai-agents`
25
+ - Do NOT invoke for test mocking – use `testing-ai-systems`
26
+
27
+ ---
28
+
29
+ ## Quick Reference
30
+
31
+ ## Decision Tree: Which Hardening Feature?
32
+
33
+ ```
34
+ What do you need?
35
+ ├── Block bad inputs before LLM call → Input guardrail
36
+ ├── Validate/filter LLM output → Output guardrail
37
+ ├── Remember context across turns → createAgentMemory
38
+ ├── Limit cost / token spend → maxTokenBudget
39
+ ├── Detect PII in prompts → PII guardrail
40
+ ├── Prevent prompt injection → Injection guardrail
41
+ └── Handle provider failures gracefully → Circuit breaker + retry
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Guardrails
47
+
48
+ Guardrails are pure validators. They check content and throw `GuardrailError` on violation. They must NOT modify the content they check.
49
+
50
+ ### Input + Output Guardrails
51
+
52
+ ```typescript
53
+ import { createGuardrail, GuardrailError } from "@directive-run/ai";
54
+
55
+ // Input guardrail – runs before each LLM call
56
+ const lengthGuardrail = createGuardrail({
57
+ name: "input-length",
58
+ type: "input",
59
+ check: async (input) => {
60
+ if (input.prompt.length > 10_000) {
61
+ throw new GuardrailError({
62
+ code: "INPUT_TOO_LONG",
63
+ message: `Input exceeds 10,000 characters (got ${input.prompt.length})`,
64
+ guardrail: "input-length",
65
+ });
66
+ }
67
+ // No return value needed – guardrails only validate
68
+ },
69
+ });
70
+
71
+ // Output guardrail – runs after each LLM response
72
+ const toxicityGuardrail = createGuardrail({
73
+ name: "toxicity-check",
74
+ type: "output",
75
+ check: async (output) => {
76
+ const score = await getToxicityScore(output.text);
77
+
78
+ if (score > 0.8) {
79
+ throw new GuardrailError({
80
+ code: "TOXIC_OUTPUT",
81
+ message: `Toxicity score ${score} exceeds threshold`,
82
+ guardrail: "toxicity-check",
83
+ });
84
+ }
85
+ },
86
+ });
87
+
88
+ // Attach to orchestrator
89
+ const orchestrator = createAgentOrchestrator({
90
+ runner: createAnthropicRunner({ model: "claude-opus-4-6", apiKey: process.env.ANTHROPIC_API_KEY }),
91
+ guardrails: [lengthGuardrail, toxicityGuardrail],
92
+ factsSchema: {
93
+ input: t.string(),
94
+ output: t.string().optional(),
95
+ status: t.string<"idle" | "done" | "blocked">(),
96
+ violationCode: t.string().optional(),
97
+ },
98
+ init: (facts) => {
99
+ facts.status = "idle";
100
+ },
101
+ resolvers: {
102
+ process: {
103
+ requirement: "PROCESS",
104
+ resolve: async (req, context) => {
105
+ try {
106
+ const result = await context.runner.run({ prompt: context.facts.input });
107
+ context.facts.output = result.text;
108
+ context.facts.status = "done";
109
+ } catch (error) {
110
+ if (error instanceof GuardrailError) {
111
+ context.facts.status = "blocked";
112
+ context.facts.violationCode = error.code;
113
+ } else {
114
+ throw error;
115
+ }
116
+ }
117
+ },
118
+ },
119
+ },
120
+ });
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Security Guardrails
126
+
127
+ ### PII Detection
128
+
129
+ ```typescript
130
+ const piiGuardrail = createGuardrail({
131
+ name: "pii-check",
132
+ type: "input",
133
+ check: async (input) => {
134
+ const patterns: Record<string, RegExp> = {
135
+ ssn: /\b\d{3}-\d{2}-\d{4}\b/,
136
+ creditCard: /\b\d{4}[\s-]\d{4}[\s-]\d{4}[\s-]\d{4}\b/,
137
+ email: /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/,
138
+ };
139
+
140
+ const detected = Object.entries(patterns)
141
+ .filter(([, re]) => re.test(input.prompt))
142
+ .map(([type]) => type);
143
+
144
+ if (detected.length > 0) {
145
+ throw new GuardrailError({
146
+ code: "PII_DETECTED",
147
+ message: `Input contains PII: ${detected.join(", ")}`,
148
+ guardrail: "pii-check",
149
+ metadata: { piiTypes: detected },
150
+ });
151
+ }
152
+ },
153
+ });
154
+ ```
155
+
156
+ ### Prompt Injection Prevention
157
+
158
+ ```typescript
159
+ const injectionGuardrail = createGuardrail({
160
+ name: "injection-prevention",
161
+ type: "input",
162
+ check: async (input) => {
163
+ const patterns = [
164
+ /ignore\s+(all\s+)?previous\s+instructions/i,
165
+ /you\s+are\s+now\s+(?:in\s+)?(?:developer|admin|god)\s+mode/i,
166
+ /disregard\s+(?:your\s+)?(?:system\s+)?instructions/i,
167
+ /<\|im_start\|>/i,
168
+ ];
169
+
170
+ const matched = patterns.some((re) => re.test(input.prompt));
171
+
172
+ if (matched) {
173
+ throw new GuardrailError({
174
+ code: "PROMPT_INJECTION",
175
+ message: "Potential prompt injection detected",
176
+ guardrail: "injection-prevention",
177
+ });
178
+ }
179
+ },
180
+ });
181
+ ```
182
+
183
+ ---
184
+
185
+ ## Agent Memory
186
+
187
+ ```typescript
188
+ import { createAgentMemory } from "@directive-run/ai";
189
+
190
+ // Sliding window: keep last N messages
191
+ const memory = createAgentMemory({
192
+ strategy: "sliding-window",
193
+ maxMessages: 20,
194
+ maxTokens: 8000,
195
+ });
196
+
197
+ // Summary: compress old context with a cheap LLM
198
+ const summaryMemory = createAgentMemory({
199
+ strategy: "summary",
200
+ maxMessages: 50,
201
+ summarizeAfter: 30,
202
+ summaryRunner: createAnthropicRunner({ model: "claude-haiku-4-5", apiKey: process.env.ANTHROPIC_API_KEY }),
203
+ });
204
+
205
+ // Semantic: retrieve relevant past messages by similarity
206
+ const semanticMemory = createAgentMemory({
207
+ strategy: "semantic",
208
+ maxRetrieved: 5,
209
+ embedder: myEmbeddingFunction,
210
+ });
211
+
212
+ // Usage in resolver
213
+ resolvers: {
214
+ respond: {
215
+ requirement: "RESPOND",
216
+ resolve: async (req, context) => {
217
+ const result = await context.runner.run({
218
+ prompt: context.facts.userMessage,
219
+ messages: context.memory.getMessages(), // inject history
220
+ });
221
+ context.facts.response = result.text;
222
+ // Memory updates automatically after each run
223
+ },
224
+ },
225
+ },
226
+ ```
227
+
228
+ ---
229
+
230
+ ## Token Budget Management
231
+
232
+ ```typescript
233
+ const orchestrator = createAgentOrchestrator({
234
+ runner: createAnthropicRunner({ model: "claude-opus-4-6", apiKey: process.env.ANTHROPIC_API_KEY }),
235
+ budget: {
236
+ maxTokenBudget: 100_000, // Hard limit – halts execution
237
+ budgetWarningThreshold: 0.8, // Fire warning at 80%
238
+ onBudgetWarning: (used, max) => {
239
+ console.warn(`Budget at ${Math.round((used / max) * 100)}%`);
240
+ },
241
+ },
242
+ factsSchema: {
243
+ input: t.string(),
244
+ output: t.string().optional(),
245
+ tokensUsed: t.number(),
246
+ },
247
+ init: (facts) => {
248
+ facts.tokensUsed = 0;
249
+ },
250
+ resolvers: {
251
+ process: {
252
+ requirement: "PROCESS",
253
+ resolve: async (req, context) => {
254
+ if (!context.budget.canAfford(estimateTokens(context.facts.input))) {
255
+ throw new Error("Insufficient token budget");
256
+ }
257
+
258
+ const result = await context.runner.run({ prompt: context.facts.input });
259
+ context.facts.output = result.text;
260
+ context.facts.tokensUsed += result.usage.totalTokens;
261
+ },
262
+ },
263
+ },
264
+ });
265
+
266
+ function estimateTokens(text: string): number {
267
+ return Math.ceil(text.length / 4); // ~4 chars per token
268
+ }
269
+ ```
270
+
271
+ ---
272
+
273
+ ## Resilience: Circuit Breaker + Retry
274
+
275
+ ```typescript
276
+ import { createCircuitBreaker } from "@directive-run/ai";
277
+
278
+ const breaker = createCircuitBreaker({
279
+ failureThreshold: 5, // Open after 5 consecutive failures
280
+ recoveryTimeout: 30_000, // Retry after 30s
281
+ halfOpenRequests: 2,
282
+ onStateChange: (from, to) => console.log(`Circuit: ${from} → ${to}`),
283
+ });
284
+
285
+ // Retry config on the resolver
286
+ resolvers: {
287
+ callLLM: {
288
+ requirement: "CALL_LLM",
289
+ retry: {
290
+ attempts: 3,
291
+ backoff: "exponential",
292
+ initialDelay: 500,
293
+ maxDelay: 10_000,
294
+ retryOn: (error) => {
295
+ return error.message.includes("rate_limit") ||
296
+ error.message.includes("overloaded");
297
+ },
298
+ },
299
+ resolve: async (req, context) => {
300
+ const result = await context.runner.run({ prompt: context.facts.input });
301
+ context.facts.output = result.text;
302
+ },
303
+ },
304
+ },
305
+ ```
306
+
307
+ ---
308
+
309
+ ## Critical Anti-Patterns
310
+
311
+ ## Guardrails that modify content
312
+
313
+ ```typescript
314
+ // WRONG – guardrails must not transform input
315
+ const bad = createGuardrail({
316
+ name: "sanitizer",
317
+ type: "input",
318
+ check: async (input) => {
319
+ input.prompt = input.prompt.replace(/badword/g, "***"); // NEVER mutate
320
+ return input; // NEVER return content
321
+ },
322
+ });
323
+
324
+ // CORRECT – only validate, throw on violation
325
+ const good = createGuardrail({
326
+ name: "content-check",
327
+ type: "input",
328
+ check: async (input) => {
329
+ if (input.prompt.includes("badword")) {
330
+ throw new GuardrailError({ code: "PROHIBITED", message: "Prohibited content", guardrail: "content-check" });
331
+ }
332
+ },
333
+ });
334
+ ```
335
+
336
+ ## Not setting token budgets in production
337
+
338
+ ```typescript
339
+ // WRONG – runaway loops = runaway costs
340
+ const orchestrator = createAgentOrchestrator({ runner, /* no budget */ });
341
+
342
+ // CORRECT
343
+ const orchestrator = createAgentOrchestrator({
344
+ runner,
345
+ budget: { maxTokenBudget: 50_000, budgetWarningThreshold: 0.8 },
346
+ });
347
+ ```
348
+
349
+ ## Catching GuardrailError silently
350
+
351
+ ```typescript
352
+ // WRONG – violations disappear
353
+ } catch (e) { /* swallowed */ }
354
+
355
+ // CORRECT
356
+ } catch (error) {
357
+ if (error instanceof GuardrailError) {
358
+ context.facts.status = "blocked";
359
+ context.facts.violationCode = error.code;
360
+ } else {
361
+ throw error;
362
+ }
363
+ }
364
+ ```
365
+
366
+ ### Resolver parameter naming
367
+ Always use `(req, context)` – never `(req, ctx)` or `(request, context)`.
368
+
369
+ ---
370
+
371
+ ## Reference Files
372
+
373
+ - `ai-guardrails-memory.md` – Full guardrail API, all memory strategies, configuration options
374
+ - `ai-budget-resilience.md` – Budget configuration, circuit breaker, retry policies, estimateTokens
375
+ - `ai-security.md` – PII patterns, injection detection, security best practices
376
+ - `examples/auth-flow.ts` – Auth-gated orchestrator with security guardrails
377
+ - `examples/fraud-analysis.ts` – Budget-aware multi-agent fraud detection