@directive-run/knowledge 0.2.0 → 0.4.2

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 (54) hide show
  1. package/README.md +3 -3
  2. package/ai/ai-adapters.md +7 -7
  3. package/ai/ai-agents-streaming.md +8 -8
  4. package/ai/ai-budget-resilience.md +5 -5
  5. package/ai/ai-communication.md +1 -1
  6. package/ai/ai-guardrails-memory.md +7 -7
  7. package/ai/ai-mcp-rag.md +5 -5
  8. package/ai/ai-multi-agent.md +14 -14
  9. package/ai/ai-orchestrator.md +8 -8
  10. package/ai/ai-security.md +2 -2
  11. package/ai/ai-tasks.md +9 -9
  12. package/ai/ai-testing-evals.md +2 -2
  13. package/core/anti-patterns.md +39 -39
  14. package/core/constraints.md +15 -15
  15. package/core/core-patterns.md +9 -9
  16. package/core/error-boundaries.md +7 -7
  17. package/core/multi-module.md +16 -16
  18. package/core/naming.md +21 -21
  19. package/core/plugins.md +14 -14
  20. package/core/react-adapter.md +13 -13
  21. package/core/resolvers.md +14 -14
  22. package/core/schema-types.md +22 -22
  23. package/core/system-api.md +16 -16
  24. package/core/testing.md +5 -5
  25. package/core/time-travel.md +20 -20
  26. package/dist/index.cjs +6 -105
  27. package/dist/index.cjs.map +1 -1
  28. package/dist/index.js +7 -97
  29. package/dist/index.js.map +1 -1
  30. package/examples/ab-testing.ts +18 -90
  31. package/examples/ai-checkpoint.ts +68 -87
  32. package/examples/ai-guardrails.ts +20 -70
  33. package/examples/auth-flow.ts +2 -2
  34. package/examples/batch-resolver.ts +19 -59
  35. package/examples/contact-form.ts +220 -69
  36. package/examples/counter.ts +77 -95
  37. package/examples/dashboard-loader.ts +37 -55
  38. package/examples/debounce-constraints.ts +0 -2
  39. package/examples/dynamic-modules.ts +17 -20
  40. package/examples/error-boundaries.ts +30 -81
  41. package/examples/newsletter.ts +22 -49
  42. package/examples/notifications.ts +24 -23
  43. package/examples/optimistic-updates.ts +36 -41
  44. package/examples/pagination.ts +2 -2
  45. package/examples/permissions.ts +22 -32
  46. package/examples/provider-routing.ts +26 -83
  47. package/examples/shopping-cart.ts +8 -8
  48. package/examples/sudoku.ts +55 -62
  49. package/examples/theme-locale.ts +4 -7
  50. package/examples/time-machine.ts +12 -90
  51. package/examples/topic-guard.ts +30 -38
  52. package/examples/url-sync.ts +8 -8
  53. package/examples/websocket.ts +5 -5
  54. package/package.json +3 -3
package/README.md CHANGED
@@ -3,9 +3,9 @@
3
3
  Knowledge files, examples, and validation scripts for the [Directive](https://directive.run) runtime.
4
4
 
5
5
  This package is the **source of truth** for all Directive coding knowledge used by:
6
- - `@directive-run/cli` generates AI rules files (`.cursorrules`, `CLAUDE.md`, etc.)
7
- - `@directive-run/claude-plugin` builds Claude Code plugin skills
8
- - `directive.run/llms.txt` website LLM reference
6
+ - `@directive-run/cli` generates AI rules files (`.cursorrules`, `CLAUDE.md`, etc.)
7
+ - `@directive-run/claude-plugin` builds Claude Code plugin skills
8
+ - `directive.run/llms.txt` website LLM reference
9
9
 
10
10
  ## Contents
11
11
 
package/ai/ai-adapters.md CHANGED
@@ -24,7 +24,7 @@ Which LLM provider?
24
24
  Every adapter MUST be imported from its subpath. The main `@directive-run/ai` entry does NOT export adapters.
25
25
 
26
26
  ```typescript
27
- // CORRECT subpath imports
27
+ // CORRECT subpath imports
28
28
  import { createAnthropicRunner } from "@directive-run/ai/anthropic";
29
29
  import { createOpenAIRunner } from "@directive-run/ai/openai";
30
30
  import { createOllamaRunner } from "@directive-run/ai/ollama";
@@ -34,11 +34,11 @@ import { createGeminiRunner } from "@directive-run/ai/gemini";
34
34
  ### Anti-Pattern #26: Importing adapters from the main entry
35
35
 
36
36
  ```typescript
37
- // WRONG adapters are NOT exported from the main package
37
+ // WRONG adapters are NOT exported from the main package
38
38
  import { createOpenAIRunner } from "@directive-run/ai";
39
39
  import { createAnthropicRunner } from "@directive-run/ai";
40
40
 
41
- // CORRECT use subpath imports
41
+ // CORRECT use subpath imports
42
42
  import { createOpenAIRunner } from "@directive-run/ai/openai";
43
43
  import { createAnthropicRunner } from "@directive-run/ai/anthropic";
44
44
  ```
@@ -136,12 +136,12 @@ const runner = createGeminiRunner({
136
136
  ### Anti-Pattern #27: Assuming provider-specific token structure
137
137
 
138
138
  ```typescript
139
- // WRONG Anthropic returns { input_tokens, output_tokens } natively
139
+ // WRONG Anthropic returns { input_tokens, output_tokens } natively
140
140
  // but adapters normalize this
141
141
  const result = await runner.run(agent, prompt);
142
142
  console.log(result.tokenUsage.input_tokens); // undefined!
143
143
 
144
- // CORRECT adapters normalize to camelCase
144
+ // CORRECT adapters normalize to camelCase
145
145
  const result = await runner.run(agent, prompt);
146
146
  console.log(result.tokenUsage.inputTokens); // number
147
147
  console.log(result.tokenUsage.outputTokens); // number
@@ -201,7 +201,7 @@ const runner = createAnthropicRunner({
201
201
  // Single-agent
202
202
  const orchestrator = createAgentOrchestrator({ runner });
203
203
 
204
- // Multi-agent same runner shared across all agents
204
+ // Multi-agent same runner shared across all agents
205
205
  const multiOrchestrator = createMultiAgentOrchestrator({
206
206
  agents: { /* ... */ },
207
207
  runner,
@@ -219,7 +219,7 @@ const runner = createAnthropicRunner({
219
219
  apiKey: process.env.ANTHROPIC_API_KEY,
220
220
  });
221
221
 
222
- // After: OpenAI same orchestrator, different runner
222
+ // After: OpenAI same orchestrator, different runner
223
223
  import { createOpenAIRunner } from "@directive-run/ai/openai";
224
224
  const runner = createOpenAIRunner({
225
225
  apiKey: process.env.OPENAI_API_KEY,
@@ -18,11 +18,11 @@ Need the complete result?
18
18
  └── Default → strategy: "buffer"
19
19
  ```
20
20
 
21
- ## AgentLike What the Runner Receives
21
+ ## AgentLike What the Runner Receives
22
22
 
23
23
  ```typescript
24
24
  interface AgentLike {
25
- // Required unique identifier
25
+ // Required unique identifier
26
26
  name: string;
27
27
 
28
28
  // System prompt / instructions
@@ -44,7 +44,7 @@ const agent: AgentLike = {
44
44
  };
45
45
  ```
46
46
 
47
- ## RunResult What the Runner Returns
47
+ ## RunResult What the Runner Returns
48
48
 
49
49
  ```typescript
50
50
  interface RunResult<T = unknown> {
@@ -143,7 +143,7 @@ Control behavior when the consumer cannot keep up with token production:
143
143
 
144
144
  ```typescript
145
145
  const stream = orchestrator.runStream(agent, "Generate long report", {
146
- backpressure: "buffer", // default buffer all tokens in memory
146
+ backpressure: "buffer", // default buffer all tokens in memory
147
147
  });
148
148
 
149
149
  const stream = orchestrator.runStream(agent, "Generate long report", {
@@ -228,12 +228,12 @@ eventSource.onmessage = (event) => {
228
228
  ### Not checking chunk.type before accessing fields
229
229
 
230
230
  ```typescript
231
- // WRONG not all chunks have .data
231
+ // WRONG not all chunks have .data
232
232
  for await (const chunk of stream) {
233
233
  console.log(chunk.data); // undefined for non-token chunks
234
234
  }
235
235
 
236
- // CORRECT switch on chunk.type
236
+ // CORRECT switch on chunk.type
237
237
  for await (const chunk of stream) {
238
238
  if (chunk.type === "token") {
239
239
  console.log(chunk.data);
@@ -244,12 +244,12 @@ for await (const chunk of stream) {
244
244
  ### Ignoring the stopped flag on guardrail chunks
245
245
 
246
246
  ```typescript
247
- // WRONG continuing after a stopping guardrail
247
+ // WRONG continuing after a stopping guardrail
248
248
  case "guardrail_triggered":
249
249
  console.log("Guardrail triggered, continuing...");
250
250
  break;
251
251
 
252
- // CORRECT check if the stream was stopped
252
+ // CORRECT check if the stream was stopped
253
253
  case "guardrail_triggered":
254
254
  if (chunk.stopped) {
255
255
  console.error(`Stopped by ${chunk.guardrailName}: ${chunk.reason}`);
@@ -55,13 +55,13 @@ const budgetRunner = withBudget(baseRunner, {
55
55
  ### Anti-Pattern #29: budgetWarningThreshold out of range
56
56
 
57
57
  ```typescript
58
- // WRONG threshold must be a 0-1 percentage
58
+ // WRONG threshold must be a 0-1 percentage
59
59
  const budgetRunner = withBudget(baseRunner, {
60
60
  budgetWarningThreshold: 80, // Not a percentage!
61
61
  budgets: [{ window: "hour", maxCost: 1.0, pricing: { inputPerMillion: 3, outputPerMillion: 15 } }],
62
62
  });
63
63
 
64
- // CORRECT use a decimal between 0 and 1
64
+ // CORRECT use a decimal between 0 and 1
65
65
  const budgetRunner = withBudget(baseRunner, {
66
66
  budgetWarningThreshold: 0.8, // 80%
67
67
  budgets: [{ window: "hour", maxCost: 1.0, pricing: { inputPerMillion: 3, outputPerMillion: 15 } }],
@@ -127,12 +127,12 @@ breaker.reset(); // Force back to closed
127
127
  ### Anti-Pattern #28: Sharing a CircuitBreaker across unrelated agents
128
128
 
129
129
  ```typescript
130
- // WRONG one failing agent opens the breaker for all agents
130
+ // WRONG one failing agent opens the breaker for all agents
131
131
  const sharedBreaker = createCircuitBreaker({ failureThreshold: 3, resetTimeout: 30000 });
132
132
  const researchRunner = sharedBreaker.wrap(baseRunner);
133
133
  const writerRunner = sharedBreaker.wrap(baseRunner); // Same breaker!
134
134
 
135
- // CORRECT each agent gets its own breaker instance
135
+ // CORRECT each agent gets its own breaker instance
136
136
  const researchBreaker = createCircuitBreaker({ failureThreshold: 3, resetTimeout: 30000 });
137
137
  const writerBreaker = createCircuitBreaker({ failureThreshold: 3, resetTimeout: 30000 });
138
138
 
@@ -207,7 +207,7 @@ const router = createConstraintRouter({
207
207
 
208
208
  ## Combining Wrappers
209
209
 
210
- Wrappers compose apply them inside-out (innermost runs first):
210
+ Wrappers compose apply them inside-out (innermost runs first):
211
211
 
212
212
  ```typescript
213
213
  import { withBudget, withRetry, withFallback } from "@directive-run/ai";
@@ -184,7 +184,7 @@ const isReady = orchestrator.system.derive.researcher.isComplete;
184
184
  The scratchpad is an ephemeral key-value store scoped to a single pattern execution. Tasks and agents in the same pattern share it:
185
185
 
186
186
  ```typescript
187
- // In a task write to scratchpad
187
+ // In a task write to scratchpad
188
188
  tasks: {
189
189
  gather: {
190
190
  run: async (input, context) => {
@@ -28,7 +28,7 @@ interface GuardrailResult {
28
28
  // Why it failed (when passed: false)
29
29
  reason?: string;
30
30
 
31
- // Modified data guardrail can transform the input/output
31
+ // Modified data guardrail can transform the input/output
32
32
  transformed?: unknown;
33
33
  }
34
34
  ```
@@ -60,7 +60,7 @@ const piiGuardrail = createPIIGuardrail({
60
60
  import { createModerationGuardrail } from "@directive-run/ai";
61
61
 
62
62
  const moderationGuardrail = createModerationGuardrail({
63
- // Custom check function return true if content is safe
63
+ // Custom check function return true if content is safe
64
64
  checkFn: async (content) => {
65
65
  const result = await moderationAPI.check(content);
66
66
 
@@ -171,7 +171,7 @@ const orchestrator = createAgentOrchestrator({
171
171
  ## Anti-Pattern #25: Catching Error Instead of GuardrailError
172
172
 
173
173
  ```typescript
174
- // WRONG loses guardrail-specific metadata
174
+ // WRONG loses guardrail-specific metadata
175
175
  try {
176
176
  const result = await orchestrator.run(agent, prompt);
177
177
  } catch (error) {
@@ -180,7 +180,7 @@ try {
180
180
  }
181
181
  }
182
182
 
183
- // CORRECT catch GuardrailError for full context
183
+ // CORRECT catch GuardrailError for full context
184
184
  import { GuardrailError } from "@directive-run/ai";
185
185
 
186
186
  try {
@@ -259,7 +259,7 @@ When messages are evicted, a summarizer condenses them:
259
259
  ```typescript
260
260
  import { createTruncationSummarizer } from "@directive-run/ai";
261
261
 
262
- // Simply drops old messages no summary generated
262
+ // Simply drops old messages no summary generated
263
263
  const summarizer = createTruncationSummarizer();
264
264
  ```
265
265
 
@@ -299,14 +299,14 @@ const orchestrator = createAgentOrchestrator({
299
299
  ## Anti-Pattern #31: Async Summarizer Without autoManage: false
300
300
 
301
301
  ```typescript
302
- // WRONG LLM summarizer is async but autoManage runs synchronously
302
+ // WRONG LLM summarizer is async but autoManage runs synchronously
303
303
  const memory = createAgentMemory({
304
304
  strategy: createSlidingWindowStrategy({ maxMessages: 20 }),
305
305
  summarizer: createLLMSummarizer(runner),
306
306
  autoManage: true, // Will not await the summarizer properly
307
307
  });
308
308
 
309
- // CORRECT disable autoManage, call memory.manage() manually
309
+ // CORRECT disable autoManage, call memory.manage() manually
310
310
  const memory = createAgentMemory({
311
311
  strategy: createSlidingWindowStrategy({ maxMessages: 20 }),
312
312
  summarizer: createLLMSummarizer(runner),
package/ai/ai-mcp-rag.md CHANGED
@@ -30,13 +30,13 @@ import { createMCPAdapter } from "@directive-run/ai";
30
30
 
31
31
  const mcp = createMCPAdapter({
32
32
  servers: [
33
- // stdio transport runs a local process
33
+ // stdio transport runs a local process
34
34
  {
35
35
  name: "tools",
36
36
  transport: "stdio",
37
37
  command: "npx mcp-server-tools",
38
38
  },
39
- // SSE transport connects to an HTTP server
39
+ // SSE transport connects to an HTTP server
40
40
  {
41
41
  name: "data",
42
42
  transport: "sse",
@@ -78,10 +78,10 @@ const agent = {
78
78
  ### Anti-Pattern #36: Importing MCP from subpath
79
79
 
80
80
  ```typescript
81
- // WRONG there is no /mcp subpath export
81
+ // WRONG there is no /mcp subpath export
82
82
  import { createMCPToolProvider } from "@directive-run/ai/mcp";
83
83
 
84
- // CORRECT MCP adapter is exported from the main package
84
+ // CORRECT MCP adapter is exported from the main package
85
85
  import { createMCPAdapter } from "@directive-run/ai";
86
86
  ```
87
87
 
@@ -193,7 +193,7 @@ await enricher.ingestFile("./docs/architecture.md", {
193
193
  ## Enriching Prompts
194
194
 
195
195
  ```typescript
196
- // Basic enrichment prepends relevant context
196
+ // Basic enrichment prepends relevant context
197
197
  const enrichedInput = await enricher.enrich("How do facts work?", {
198
198
  prefix: "Use this context to answer:\n",
199
199
  });
@@ -67,7 +67,7 @@ const orchestrator = createMultiAgentOrchestrator({
67
67
  runner,
68
68
  });
69
69
 
70
- // REQUIRED for multi-agent must call start() before running patterns
70
+ // REQUIRED for multi-agent must call start() before running patterns
71
71
  orchestrator.start();
72
72
 
73
73
  const result = await orchestrator.runPattern("pipeline", "Write about AI");
@@ -75,7 +75,7 @@ const result = await orchestrator.runPattern("pipeline", "Write about AI");
75
75
 
76
76
  ## Pattern Details
77
77
 
78
- ### parallel Run agents concurrently, merge results
78
+ ### parallel Run agents concurrently, merge results
79
79
 
80
80
  ```typescript
81
81
  const brainstorm = parallel(
@@ -91,21 +91,21 @@ const brainstorm = parallel(
91
91
  );
92
92
  ```
93
93
 
94
- ### sequential Chain agents in order
94
+ ### sequential Chain agents in order
95
95
 
96
96
  ```typescript
97
97
  // Each agent receives the previous agent's output as its prompt
98
98
  const pipeline = sequential(["researcher", "writer", "editor"]);
99
99
  ```
100
100
 
101
- ### supervisor One agent delegates to workers
101
+ ### supervisor One agent delegates to workers
102
102
 
103
103
  ```typescript
104
104
  // Editor decides which worker to invoke and when to stop
105
105
  const managed = supervisor("editor", ["researcher", "writer"]);
106
106
  ```
107
107
 
108
- ### dag Directed acyclic graph of dependencies
108
+ ### dag Directed acyclic graph of dependencies
109
109
 
110
110
  ```typescript
111
111
  // DagNode shape
@@ -132,7 +132,7 @@ const workflow = dag([
132
132
  ]);
133
133
  ```
134
134
 
135
- ### reflect Agent critiques and revises its own output
135
+ ### reflect Agent critiques and revises its own output
136
136
 
137
137
  ```typescript
138
138
  const selfImprove = reflect("writer", {
@@ -143,7 +143,7 @@ const selfImprove = reflect("writer", {
143
143
  });
144
144
  ```
145
145
 
146
- ### race First agent to finish wins
146
+ ### race First agent to finish wins
147
147
 
148
148
  ```typescript
149
149
  const fastest = race(["researcher", "writer"], {
@@ -152,7 +152,7 @@ const fastest = race(["researcher", "writer"], {
152
152
  });
153
153
  ```
154
154
 
155
- ### debate Agents argue to consensus
155
+ ### debate Agents argue to consensus
156
156
 
157
157
  ```typescript
158
158
  const consensus = debate(["researcher", "writer"], {
@@ -161,7 +161,7 @@ const consensus = debate(["researcher", "writer"], {
161
161
  });
162
162
  ```
163
163
 
164
- ### goal Iterate until a condition is met
164
+ ### goal Iterate until a condition is met
165
165
 
166
166
  ```typescript
167
167
  const iterative = goal("researcher", {
@@ -220,7 +220,7 @@ const workflow = dag([
220
220
  ### #24: Forgetting start() for multi-agent
221
221
 
222
222
  ```typescript
223
- // WRONG multi-agent orchestrators require explicit start()
223
+ // WRONG multi-agent orchestrators require explicit start()
224
224
  const orchestrator = createMultiAgentOrchestrator({ agents, runner });
225
225
  const result = await orchestrator.runPattern("pipeline", "prompt");
226
226
  // Error: Orchestrator not started
@@ -234,12 +234,12 @@ const result = await orchestrator.runPattern("pipeline", "prompt");
234
234
  ### #30: race minSuccess greater than agent count
235
235
 
236
236
  ```typescript
237
- // WRONG minSuccess cannot exceed the number of agents
237
+ // WRONG minSuccess cannot exceed the number of agents
238
238
  const broken = race(["researcher", "writer"], {
239
239
  minSuccess: 3, // Only 2 agents, will never satisfy
240
240
  });
241
241
 
242
- // CORRECT minSuccess <= agents.length
242
+ // CORRECT minSuccess <= agents.length
243
243
  const working = race(["researcher", "writer"], {
244
244
  minSuccess: 1,
245
245
  });
@@ -248,13 +248,13 @@ const working = race(["researcher", "writer"], {
248
248
  ### Reusing agent names across patterns
249
249
 
250
250
  ```typescript
251
- // WRONG agent names must match keys in the agents config
251
+ // WRONG agent names must match keys in the agents config
252
252
  patterns: {
253
253
  pipeline: sequential(["research-agent", "write-agent"]),
254
254
  // These don't match the keys "researcher", "writer"
255
255
  },
256
256
 
257
- // CORRECT use the exact keys from agents config
257
+ // CORRECT use the exact keys from agents config
258
258
  patterns: {
259
259
  pipeline: sequential(["researcher", "writer"]),
260
260
  },
@@ -156,13 +156,13 @@ const restored = createAgentOrchestrator({
156
156
  ### #21: TypeScript types instead of t.*() for factsSchema
157
157
 
158
158
  ```typescript
159
- // WRONG TS types are erased at runtime, no schema validation
159
+ // WRONG TS types are erased at runtime, no schema validation
160
160
  const orchestrator = createAgentOrchestrator({
161
161
  runner,
162
162
  factsSchema: {} as { confidence: number; analysis: string },
163
163
  });
164
164
 
165
- // CORRECT use t.*() builders for runtime schema
165
+ // CORRECT use t.*() builders for runtime schema
166
166
  const orchestrator = createAgentOrchestrator({
167
167
  runner,
168
168
  factsSchema: {
@@ -175,24 +175,24 @@ const orchestrator = createAgentOrchestrator({
175
175
  ### #22: Mutating arrays/objects in place
176
176
 
177
177
  ```typescript
178
- // WRONG proxy cannot detect in-place mutations
178
+ // WRONG proxy cannot detect in-place mutations
179
179
  context.facts.cache.push("new-item");
180
180
 
181
- // CORRECT replace the entire value
181
+ // CORRECT replace the entire value
182
182
  context.facts.cache = [...context.facts.cache, "new-item"];
183
183
  ```
184
184
 
185
185
  ### #23: Returning data from resolve
186
186
 
187
187
  ```typescript
188
- // WRONG resolvers return void, not data
188
+ // WRONG resolvers return void, not data
189
189
  resolve: async (req, context) => {
190
190
  const result = await analyzeData(req.input);
191
191
 
192
192
  return result; // Return value is ignored
193
193
  },
194
194
 
195
- // CORRECT mutate context.facts to store results
195
+ // CORRECT mutate context.facts to store results
196
196
  resolve: async (req, context) => {
197
197
  const result = await analyzeData(req.input);
198
198
  context.facts.analysis = result;
@@ -202,11 +202,11 @@ resolve: async (req, context) => {
202
202
  ### #24: Forgetting start() for multi-agent
203
203
 
204
204
  ```typescript
205
- // WRONG multi-agent orchestrators require explicit start()
205
+ // WRONG multi-agent orchestrators require explicit start()
206
206
  const orchestrator = createMultiAgentOrchestrator({ agents, runner });
207
207
  const result = await orchestrator.runPattern("pipeline", "prompt");
208
208
 
209
- // CORRECT call start() before running patterns
209
+ // CORRECT call start() before running patterns
210
210
  const orchestrator = createMultiAgentOrchestrator({ agents, runner });
211
211
  orchestrator.start();
212
212
  const result = await orchestrator.runPattern("pipeline", "prompt");
package/ai/ai-security.md CHANGED
@@ -224,10 +224,10 @@ const orchestrator = createAgentOrchestrator({
224
224
  ### Input Validation
225
225
 
226
226
  ```typescript
227
- // WRONG passing raw user input to the agent
227
+ // WRONG passing raw user input to the agent
228
228
  const result = await orchestrator.run(agent, userInput);
229
229
 
230
- // CORRECT validate and sanitize input first
230
+ // CORRECT validate and sanitize input first
231
231
  const sanitized = sanitizeInput(userInput);
232
232
  const result = await orchestrator.run(agent, sanitized);
233
233
  ```
package/ai/ai-tasks.md CHANGED
@@ -21,7 +21,7 @@ Does this work need an LLM?
21
21
 
22
22
  ```typescript
23
23
  interface TaskRegistration {
24
- // The work function input is ALWAYS a string
24
+ // The work function input is ALWAYS a string
25
25
  run: (input: string, context: TaskContext) => Promise<string>;
26
26
 
27
27
  // Human-readable label for debugging/logging
@@ -184,11 +184,11 @@ tasks: {
184
184
  ### #33: Tasks calling agents internally
185
185
 
186
186
  ```typescript
187
- // WRONG tasks cannot invoke agents
187
+ // WRONG tasks cannot invoke agents
188
188
  tasks: {
189
189
  enhance: {
190
190
  run: async (input, context) => {
191
- // Tasks have no runner access this won't work
191
+ // Tasks have no runner access this won't work
192
192
  const result = await runner.run(someAgent, input);
193
193
 
194
194
  return result.output;
@@ -196,7 +196,7 @@ tasks: {
196
196
  },
197
197
  },
198
198
 
199
- // CORRECT use a pattern to compose agents and tasks
199
+ // CORRECT use a pattern to compose agents and tasks
200
200
  patterns: {
201
201
  enhance: sequential(["enhancer-agent", "format-task"]),
202
202
  },
@@ -205,17 +205,17 @@ patterns: {
205
205
  ### #34: Expecting structured input (not a string)
206
206
 
207
207
  ```typescript
208
- // WRONG task input is always a string
208
+ // WRONG task input is always a string
209
209
  tasks: {
210
210
  process: {
211
211
  run: async (input, context) => {
212
- // input.items is undefined input is a string
212
+ // input.items is undefined input is a string
213
213
  return input.items.map((i) => i.name).join(", ");
214
214
  },
215
215
  },
216
216
  },
217
217
 
218
- // CORRECT parse the string input
218
+ // CORRECT parse the string input
219
219
  tasks: {
220
220
  process: {
221
221
  run: async (input, context) => {
@@ -230,7 +230,7 @@ tasks: {
230
230
  ### #35: Task and agent IDs collide
231
231
 
232
232
  ```typescript
233
- // WRONG "researcher" exists as both agent and task
233
+ // WRONG "researcher" exists as both agent and task
234
234
  agents: {
235
235
  researcher: { name: "researcher", instructions: "...", model: "claude-sonnet-4-5" },
236
236
  },
@@ -238,7 +238,7 @@ tasks: {
238
238
  researcher: { run: async (input) => input }, // Name collision!
239
239
  },
240
240
 
241
- // CORRECT use distinct names
241
+ // CORRECT use distinct names
242
242
  agents: {
243
243
  researcher: { name: "researcher", instructions: "...", model: "claude-sonnet-4-5" },
244
244
  },
@@ -254,7 +254,7 @@ const evaluator = createEvaluator({
254
254
  ### Anti-Pattern #32: Side effects in evaluator scorer
255
255
 
256
256
  ```typescript
257
- // WRONG scorers must be pure functions
257
+ // WRONG scorers must be pure functions
258
258
  {
259
259
  name: "quality",
260
260
  scorer: (input, output) => {
@@ -266,7 +266,7 @@ const evaluator = createEvaluator({
266
266
  },
267
267
  }
268
268
 
269
- // CORRECT scorers are pure, return score + reason only
269
+ // CORRECT scorers are pure, return score + reason only
270
270
  {
271
271
  name: "quality",
272
272
  scorer: (input, output) => {