mcp-rubber-duck 1.7.0 → 1.9.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 (169) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +274 -2
  3. package/audit-ci.json +2 -1
  4. package/dist/config/config.d.ts +2 -0
  5. package/dist/config/config.d.ts.map +1 -1
  6. package/dist/config/config.js +144 -1
  7. package/dist/config/config.js.map +1 -1
  8. package/dist/config/types.d.ts +1084 -2
  9. package/dist/config/types.d.ts.map +1 -1
  10. package/dist/config/types.js +59 -0
  11. package/dist/config/types.js.map +1 -1
  12. package/dist/guardrails/context.d.ts +10 -0
  13. package/dist/guardrails/context.d.ts.map +1 -0
  14. package/dist/guardrails/context.js +35 -0
  15. package/dist/guardrails/context.js.map +1 -0
  16. package/dist/guardrails/errors.d.ts +26 -0
  17. package/dist/guardrails/errors.d.ts.map +1 -0
  18. package/dist/guardrails/errors.js +42 -0
  19. package/dist/guardrails/errors.js.map +1 -0
  20. package/dist/guardrails/index.d.ts +6 -0
  21. package/dist/guardrails/index.d.ts.map +1 -0
  22. package/dist/guardrails/index.js +11 -0
  23. package/dist/guardrails/index.js.map +1 -0
  24. package/dist/guardrails/plugins/base-plugin.d.ts +35 -0
  25. package/dist/guardrails/plugins/base-plugin.d.ts.map +1 -0
  26. package/dist/guardrails/plugins/base-plugin.js +70 -0
  27. package/dist/guardrails/plugins/base-plugin.js.map +1 -0
  28. package/dist/guardrails/plugins/index.d.ts +6 -0
  29. package/dist/guardrails/plugins/index.d.ts.map +1 -0
  30. package/dist/guardrails/plugins/index.js +6 -0
  31. package/dist/guardrails/plugins/index.js.map +1 -0
  32. package/dist/guardrails/plugins/pattern-blocker.d.ts +27 -0
  33. package/dist/guardrails/plugins/pattern-blocker.d.ts.map +1 -0
  34. package/dist/guardrails/plugins/pattern-blocker.js +140 -0
  35. package/dist/guardrails/plugins/pattern-blocker.js.map +1 -0
  36. package/dist/guardrails/plugins/pii-redactor/detectors.d.ts +40 -0
  37. package/dist/guardrails/plugins/pii-redactor/detectors.d.ts.map +1 -0
  38. package/dist/guardrails/plugins/pii-redactor/detectors.js +134 -0
  39. package/dist/guardrails/plugins/pii-redactor/detectors.js.map +1 -0
  40. package/dist/guardrails/plugins/pii-redactor/index.d.ts +28 -0
  41. package/dist/guardrails/plugins/pii-redactor/index.d.ts.map +1 -0
  42. package/dist/guardrails/plugins/pii-redactor/index.js +157 -0
  43. package/dist/guardrails/plugins/pii-redactor/index.js.map +1 -0
  44. package/dist/guardrails/plugins/pii-redactor/pseudonymizer.d.ts +33 -0
  45. package/dist/guardrails/plugins/pii-redactor/pseudonymizer.d.ts.map +1 -0
  46. package/dist/guardrails/plugins/pii-redactor/pseudonymizer.js +70 -0
  47. package/dist/guardrails/plugins/pii-redactor/pseudonymizer.js.map +1 -0
  48. package/dist/guardrails/plugins/rate-limiter.d.ts +28 -0
  49. package/dist/guardrails/plugins/rate-limiter.d.ts.map +1 -0
  50. package/dist/guardrails/plugins/rate-limiter.js +91 -0
  51. package/dist/guardrails/plugins/rate-limiter.js.map +1 -0
  52. package/dist/guardrails/plugins/token-limiter.d.ts +30 -0
  53. package/dist/guardrails/plugins/token-limiter.d.ts.map +1 -0
  54. package/dist/guardrails/plugins/token-limiter.js +98 -0
  55. package/dist/guardrails/plugins/token-limiter.js.map +1 -0
  56. package/dist/guardrails/service.d.ts +38 -0
  57. package/dist/guardrails/service.d.ts.map +1 -0
  58. package/dist/guardrails/service.js +183 -0
  59. package/dist/guardrails/service.js.map +1 -0
  60. package/dist/guardrails/types.d.ts +96 -0
  61. package/dist/guardrails/types.d.ts.map +1 -0
  62. package/dist/guardrails/types.js +2 -0
  63. package/dist/guardrails/types.js.map +1 -0
  64. package/dist/prompts/architecture.d.ts +6 -0
  65. package/dist/prompts/architecture.d.ts.map +1 -0
  66. package/dist/prompts/architecture.js +103 -0
  67. package/dist/prompts/architecture.js.map +1 -0
  68. package/dist/prompts/assumptions.d.ts +6 -0
  69. package/dist/prompts/assumptions.d.ts.map +1 -0
  70. package/dist/prompts/assumptions.js +72 -0
  71. package/dist/prompts/assumptions.js.map +1 -0
  72. package/dist/prompts/blindspots.d.ts +6 -0
  73. package/dist/prompts/blindspots.d.ts.map +1 -0
  74. package/dist/prompts/blindspots.js +71 -0
  75. package/dist/prompts/blindspots.js.map +1 -0
  76. package/dist/prompts/diverge-converge.d.ts +6 -0
  77. package/dist/prompts/diverge-converge.d.ts.map +1 -0
  78. package/dist/prompts/diverge-converge.js +85 -0
  79. package/dist/prompts/diverge-converge.js.map +1 -0
  80. package/dist/prompts/index.d.ts +22 -0
  81. package/dist/prompts/index.d.ts.map +1 -0
  82. package/dist/prompts/index.js +57 -0
  83. package/dist/prompts/index.js.map +1 -0
  84. package/dist/prompts/perspectives.d.ts +7 -0
  85. package/dist/prompts/perspectives.d.ts.map +1 -0
  86. package/dist/prompts/perspectives.js +65 -0
  87. package/dist/prompts/perspectives.js.map +1 -0
  88. package/dist/prompts/red-team.d.ts +6 -0
  89. package/dist/prompts/red-team.d.ts.map +1 -0
  90. package/dist/prompts/red-team.js +83 -0
  91. package/dist/prompts/red-team.js.map +1 -0
  92. package/dist/prompts/reframe.d.ts +6 -0
  93. package/dist/prompts/reframe.d.ts.map +1 -0
  94. package/dist/prompts/reframe.js +71 -0
  95. package/dist/prompts/reframe.js.map +1 -0
  96. package/dist/prompts/tradeoffs.d.ts +6 -0
  97. package/dist/prompts/tradeoffs.d.ts.map +1 -0
  98. package/dist/prompts/tradeoffs.js +87 -0
  99. package/dist/prompts/tradeoffs.js.map +1 -0
  100. package/dist/prompts/types.d.ts +14 -0
  101. package/dist/prompts/types.d.ts.map +1 -0
  102. package/dist/prompts/types.js +2 -0
  103. package/dist/prompts/types.js.map +1 -0
  104. package/dist/providers/duck-provider-enhanced.d.ts +2 -1
  105. package/dist/providers/duck-provider-enhanced.d.ts.map +1 -1
  106. package/dist/providers/duck-provider-enhanced.js +55 -6
  107. package/dist/providers/duck-provider-enhanced.js.map +1 -1
  108. package/dist/providers/enhanced-manager.d.ts +2 -1
  109. package/dist/providers/enhanced-manager.d.ts.map +1 -1
  110. package/dist/providers/enhanced-manager.js +3 -3
  111. package/dist/providers/enhanced-manager.js.map +1 -1
  112. package/dist/providers/manager.d.ts +3 -1
  113. package/dist/providers/manager.d.ts.map +1 -1
  114. package/dist/providers/manager.js +4 -2
  115. package/dist/providers/manager.js.map +1 -1
  116. package/dist/providers/provider.d.ts +3 -1
  117. package/dist/providers/provider.d.ts.map +1 -1
  118. package/dist/providers/provider.js +43 -3
  119. package/dist/providers/provider.js.map +1 -1
  120. package/dist/server.d.ts +1 -0
  121. package/dist/server.d.ts.map +1 -1
  122. package/dist/server.js +48 -7
  123. package/dist/server.js.map +1 -1
  124. package/dist/services/function-bridge.d.ts +3 -1
  125. package/dist/services/function-bridge.d.ts.map +1 -1
  126. package/dist/services/function-bridge.js +40 -1
  127. package/dist/services/function-bridge.js.map +1 -1
  128. package/package.json +1 -1
  129. package/src/config/config.ts +187 -1
  130. package/src/config/types.ts +73 -0
  131. package/src/guardrails/context.ts +37 -0
  132. package/src/guardrails/errors.ts +46 -0
  133. package/src/guardrails/index.ts +20 -0
  134. package/src/guardrails/plugins/base-plugin.ts +103 -0
  135. package/src/guardrails/plugins/index.ts +5 -0
  136. package/src/guardrails/plugins/pattern-blocker.ts +190 -0
  137. package/src/guardrails/plugins/pii-redactor/detectors.ts +200 -0
  138. package/src/guardrails/plugins/pii-redactor/index.ts +203 -0
  139. package/src/guardrails/plugins/pii-redactor/pseudonymizer.ts +91 -0
  140. package/src/guardrails/plugins/rate-limiter.ts +142 -0
  141. package/src/guardrails/plugins/token-limiter.ts +155 -0
  142. package/src/guardrails/service.ts +209 -0
  143. package/src/guardrails/types.ts +120 -0
  144. package/src/prompts/architecture.ts +111 -0
  145. package/src/prompts/assumptions.ts +80 -0
  146. package/src/prompts/blindspots.ts +79 -0
  147. package/src/prompts/diverge-converge.ts +92 -0
  148. package/src/prompts/index.ts +63 -0
  149. package/src/prompts/perspectives.ts +73 -0
  150. package/src/prompts/red-team.ts +91 -0
  151. package/src/prompts/reframe.ts +78 -0
  152. package/src/prompts/tradeoffs.ts +95 -0
  153. package/src/prompts/types.ts +14 -0
  154. package/src/providers/duck-provider-enhanced.ts +76 -7
  155. package/src/providers/enhanced-manager.ts +5 -3
  156. package/src/providers/manager.ts +6 -3
  157. package/src/providers/provider.ts +57 -6
  158. package/src/server.ts +55 -6
  159. package/src/services/function-bridge.ts +53 -2
  160. package/tests/guardrails/config.test.ts +267 -0
  161. package/tests/guardrails/errors.test.ts +109 -0
  162. package/tests/guardrails/plugins/pattern-blocker.test.ts +309 -0
  163. package/tests/guardrails/plugins/pii-redactor.test.ts +1004 -0
  164. package/tests/guardrails/plugins/rate-limiter.test.ts +310 -0
  165. package/tests/guardrails/plugins/token-limiter.test.ts +216 -0
  166. package/tests/guardrails/service.test.ts +911 -0
  167. package/tests/mcp-bridge.test.ts +248 -0
  168. package/tests/prompts.test.ts +314 -0
  169. package/tests/providers.test.ts +739 -0
@@ -0,0 +1,209 @@
1
+ import { GuardrailPlugin, GuardrailPhase, GuardrailContext, GuardrailResult, CreateContextOptions } from './types.js';
2
+ import { createGuardrailContext } from './context.js';
3
+ import { GuardrailsConfig, GuardrailsPluginsConfig } from '../config/types.js';
4
+ import { logger } from '../utils/logger.js';
5
+
6
+ /**
7
+ * Main service that orchestrates guardrail plugins
8
+ */
9
+ export class GuardrailsService {
10
+ private plugins: GuardrailPlugin[] = [];
11
+ private config: GuardrailsConfig;
12
+ private enabled: boolean = false;
13
+
14
+ constructor(config?: Partial<GuardrailsConfig>) {
15
+ this.config = {
16
+ enabled: config?.enabled ?? false,
17
+ log_violations: config?.log_violations ?? true,
18
+ log_modifications: config?.log_modifications ?? false,
19
+ fail_open: config?.fail_open ?? false,
20
+ plugins: config?.plugins,
21
+ };
22
+ // Start disabled - will be enabled after successful initialization with plugins
23
+ this.enabled = false;
24
+ }
25
+
26
+ /**
27
+ * Initialize the service and all configured plugins
28
+ */
29
+ async initialize(): Promise<void> {
30
+ if (!this.config.enabled) {
31
+ logger.info('Guardrails disabled in configuration');
32
+ return;
33
+ }
34
+
35
+ const pluginConfigs = this.config.plugins || {};
36
+
37
+ // Load plugins in order
38
+ await this.loadPluginsFromConfig(pluginConfigs);
39
+
40
+ // Sort by priority (lower = runs first)
41
+ this.plugins.sort((a, b) => a.priority - b.priority);
42
+
43
+ this.enabled = this.plugins.length > 0;
44
+ logger.info(`Guardrails initialized with ${this.plugins.length} plugins`);
45
+ }
46
+
47
+ private async loadPluginsFromConfig(pluginConfigs: Partial<GuardrailsPluginsConfig>): Promise<void> {
48
+ const pluginOrder: Array<[string, unknown]> = [
49
+ ['rate_limiter', pluginConfigs.rate_limiter],
50
+ ['token_limiter', pluginConfigs.token_limiter],
51
+ ['pii_redactor', pluginConfigs.pii_redactor],
52
+ ['pattern_blocker', pluginConfigs.pattern_blocker],
53
+ ];
54
+
55
+ for (const [pluginName, pluginConfig] of pluginOrder) {
56
+ if (!pluginConfig || !(pluginConfig as { enabled?: boolean }).enabled) {
57
+ continue;
58
+ }
59
+
60
+ try {
61
+ const plugin = await this.loadPlugin(pluginName);
62
+ await plugin.initialize(pluginConfig as Record<string, unknown>);
63
+ if ((pluginConfig as { priority?: number }).priority !== undefined) {
64
+ plugin.priority = (pluginConfig as { priority: number }).priority;
65
+ }
66
+ this.plugins.push(plugin);
67
+ logger.info(`Guardrail plugin '${pluginName}' initialized`);
68
+ } catch (error) {
69
+ logger.error(`Failed to initialize guardrail plugin '${pluginName}':`, error);
70
+ }
71
+ }
72
+ }
73
+
74
+ private async loadPlugin(name: string): Promise<GuardrailPlugin> {
75
+ // Dynamic plugin loading
76
+ switch (name) {
77
+ case 'rate_limiter': {
78
+ const { RateLimiterPlugin } = await import('./plugins/rate-limiter.js');
79
+ return new RateLimiterPlugin();
80
+ }
81
+ case 'token_limiter': {
82
+ const { TokenLimiterPlugin } = await import('./plugins/token-limiter.js');
83
+ return new TokenLimiterPlugin();
84
+ }
85
+ case 'pattern_blocker': {
86
+ const { PatternBlockerPlugin } = await import('./plugins/pattern-blocker.js');
87
+ return new PatternBlockerPlugin();
88
+ }
89
+ case 'pii_redactor': {
90
+ const { PIIRedactorPlugin } = await import('./plugins/pii-redactor/index.js');
91
+ return new PIIRedactorPlugin();
92
+ }
93
+ default:
94
+ throw new Error(`Unknown guardrail plugin: ${name}`);
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Check if guardrails are enabled
100
+ */
101
+ isEnabled(): boolean {
102
+ return this.enabled;
103
+ }
104
+
105
+ /**
106
+ * Create a new context for guardrail execution
107
+ */
108
+ createContext(options: CreateContextOptions): GuardrailContext {
109
+ return createGuardrailContext(options);
110
+ }
111
+
112
+ /**
113
+ * Execute all relevant plugins for a given phase
114
+ */
115
+ async execute(phase: GuardrailPhase, context: GuardrailContext): Promise<GuardrailResult> {
116
+ if (!this.enabled) {
117
+ return { action: 'allow', context };
118
+ }
119
+
120
+ const relevantPlugins = this.plugins.filter(
121
+ (p) => p.enabled && p.phases.includes(phase)
122
+ );
123
+
124
+ // Track logged items to avoid duplicates
125
+ let lastViolationCount = 0;
126
+ let lastModificationCount = 0;
127
+ let wasModified = false;
128
+
129
+ for (const plugin of relevantPlugins) {
130
+ try {
131
+ const result = await plugin.execute(phase, context);
132
+
133
+ // Log only NEW violations if configured
134
+ if (this.config.log_violations && context.violations.length > lastViolationCount) {
135
+ for (let i = lastViolationCount; i < context.violations.length; i++) {
136
+ const violation = context.violations[i];
137
+ logger.warn(`Guardrail violation: ${violation.pluginName} - ${violation.message}`, {
138
+ rule: violation.rule,
139
+ severity: violation.severity,
140
+ details: violation.details,
141
+ });
142
+ }
143
+ lastViolationCount = context.violations.length;
144
+ }
145
+
146
+ // Log only NEW modifications if configured
147
+ if (this.config.log_modifications && context.modifications.length > lastModificationCount) {
148
+ for (let i = lastModificationCount; i < context.modifications.length; i++) {
149
+ const mod = context.modifications[i];
150
+ logger.info(`Guardrail modification: ${mod.pluginName} - ${mod.reason}`, {
151
+ field: mod.field,
152
+ });
153
+ }
154
+ lastModificationCount = context.modifications.length;
155
+ }
156
+
157
+ if (result.action === 'block') {
158
+ logger.warn(`Request blocked by guardrail '${plugin.name}': ${result.blockReason}`);
159
+ return result;
160
+ }
161
+
162
+ // Track if any plugin modified the context
163
+ if (result.action === 'modify') {
164
+ wasModified = true;
165
+ }
166
+
167
+ // Update context for next plugin
168
+ context = result.context;
169
+ } catch (error) {
170
+ const errorMessage = error instanceof Error ? error.message : String(error);
171
+ logger.error(`Guardrail plugin '${plugin.name}' error:`, error);
172
+
173
+ if (!this.config.fail_open) {
174
+ return {
175
+ action: 'block',
176
+ context,
177
+ blockedBy: plugin.name,
178
+ blockReason: `Plugin error: ${errorMessage}`,
179
+ };
180
+ }
181
+ // fail_open: continue to next plugin
182
+ }
183
+ }
184
+
185
+ return { action: wasModified ? 'modify' : 'allow', context };
186
+ }
187
+
188
+ /**
189
+ * Shutdown the service and all plugins
190
+ */
191
+ async shutdown(): Promise<void> {
192
+ for (const plugin of this.plugins) {
193
+ try {
194
+ await plugin.shutdown();
195
+ } catch (error) {
196
+ logger.error(`Error shutting down plugin '${plugin.name}':`, error);
197
+ }
198
+ }
199
+ this.plugins = [];
200
+ this.enabled = false;
201
+ }
202
+
203
+ /**
204
+ * Get list of loaded plugins
205
+ */
206
+ getPlugins(): GuardrailPlugin[] {
207
+ return [...this.plugins];
208
+ }
209
+ }
@@ -0,0 +1,120 @@
1
+ import { ConversationMessage } from '../config/types.js';
2
+
3
+ /**
4
+ * Phases in the guardrail pipeline where plugins can intercept
5
+ */
6
+ export type GuardrailPhase =
7
+ | 'pre_request' // Before LLM API call
8
+ | 'post_response' // After LLM response, before tool handling
9
+ | 'pre_tool_input' // Before MCP tool execution
10
+ | 'post_tool_output' // After MCP tool returns
11
+ | 'pre_cache'; // Before caching response
12
+
13
+ /**
14
+ * Action to take after guardrail evaluation
15
+ */
16
+ export type GuardrailAction = 'allow' | 'block' | 'modify';
17
+
18
+ /**
19
+ * Severity levels for violations
20
+ */
21
+ export type ViolationSeverity = 'info' | 'warning' | 'error' | 'critical';
22
+
23
+ /**
24
+ * A violation detected by a guardrail plugin
25
+ */
26
+ export interface GuardrailViolation {
27
+ pluginName: string;
28
+ phase: GuardrailPhase;
29
+ rule: string;
30
+ severity: ViolationSeverity;
31
+ message: string;
32
+ details?: Record<string, unknown>;
33
+ }
34
+
35
+ /**
36
+ * A modification made by a guardrail plugin
37
+ */
38
+ export interface GuardrailModification {
39
+ pluginName: string;
40
+ phase: GuardrailPhase;
41
+ field: string;
42
+ originalValue?: unknown;
43
+ newValue?: unknown;
44
+ reason: string;
45
+ }
46
+
47
+ /**
48
+ * Context passed through the guardrail pipeline
49
+ */
50
+ export interface GuardrailContext {
51
+ // Request metadata
52
+ requestId: string;
53
+ provider: string;
54
+ model: string;
55
+ timestamp: Date;
56
+
57
+ // Phase-specific data (mutable by plugins)
58
+ messages: ConversationMessage[];
59
+ prompt?: string;
60
+ response?: string;
61
+ toolName?: string;
62
+ toolArgs?: Record<string, unknown>;
63
+ toolResult?: unknown;
64
+
65
+ // Tracking data (persisted across phases)
66
+ metadata: Map<string, unknown>; // For plugins to store state
67
+ violations: GuardrailViolation[]; // Accumulated violations
68
+ modifications: GuardrailModification[]; // Tracking changes made
69
+ }
70
+
71
+ /**
72
+ * Result from a guardrail plugin execution
73
+ */
74
+ export interface GuardrailResult {
75
+ action: GuardrailAction;
76
+ context: GuardrailContext;
77
+ blockedBy?: string; // Plugin name that blocked
78
+ blockReason?: string;
79
+ }
80
+
81
+ /**
82
+ * Base interface for guardrail plugins
83
+ */
84
+ export interface GuardrailPlugin {
85
+ /** Unique plugin name */
86
+ name: string;
87
+
88
+ /** Whether the plugin is currently enabled */
89
+ enabled: boolean;
90
+
91
+ /** Execution priority (lower = runs first) */
92
+ priority: number;
93
+
94
+ /** Which phases this plugin handles */
95
+ phases: GuardrailPhase[];
96
+
97
+ /** Initialize the plugin with its configuration */
98
+ initialize(config: Record<string, unknown>): Promise<void>;
99
+
100
+ /** Execute the plugin for a specific phase */
101
+ execute(phase: GuardrailPhase, context: GuardrailContext): Promise<GuardrailResult>;
102
+
103
+ /** Cleanup plugin resources */
104
+ shutdown(): Promise<void>;
105
+ }
106
+
107
+ /**
108
+ * Options for creating a guardrail context
109
+ */
110
+ export interface CreateContextOptions {
111
+ requestId?: string;
112
+ provider?: string;
113
+ model?: string;
114
+ messages?: ConversationMessage[];
115
+ prompt?: string;
116
+ response?: string;
117
+ toolName?: string;
118
+ toolArgs?: Record<string, unknown>;
119
+ toolResult?: unknown;
120
+ }
@@ -0,0 +1,111 @@
1
+ import { PromptDefinition } from './types.js';
2
+
3
+ /**
4
+ * Prompt for structured architecture and design reviews.
5
+ */
6
+ export const architecturePrompt: PromptDefinition = {
7
+ name: 'architecture',
8
+ description:
9
+ 'Structured architecture or design review from multiple engineering perspectives. Each reviewer focuses on different cross-cutting concerns.',
10
+ arguments: [
11
+ {
12
+ name: 'design',
13
+ description: 'Description of the architecture, system design, or technical approach',
14
+ required: true,
15
+ },
16
+ {
17
+ name: 'workloads',
18
+ description: 'Key use cases, workloads, or scenarios the design must handle',
19
+ required: true,
20
+ },
21
+ {
22
+ name: 'priorities',
23
+ description:
24
+ 'Non-functional priorities (e.g., "latency, cost, simplicity, observability")',
25
+ required: true,
26
+ },
27
+ {
28
+ name: 'uncertainties',
29
+ description: 'Areas where you feel most unsure or want extra scrutiny',
30
+ required: false,
31
+ },
32
+ ],
33
+ buildMessages: (args: Record<string, string>) => {
34
+ const { design, workloads, priorities, uncertainties } = args;
35
+
36
+ if (!design) {
37
+ throw new Error('design argument is required');
38
+ }
39
+ if (!workloads) {
40
+ throw new Error('workloads argument is required');
41
+ }
42
+ if (!priorities) {
43
+ throw new Error('priorities argument is required');
44
+ }
45
+
46
+ let messageText = `Review this architecture from multiple engineering perspectives:
47
+
48
+ **DESIGN:**
49
+ ${design}
50
+
51
+ **KEY WORKLOADS/USE CASES:**
52
+ ${workloads}
53
+
54
+ **PRIORITIES:**
55
+ ${priorities}
56
+ `;
57
+
58
+ if (uncertainties) {
59
+ messageText += `
60
+ **AREAS OF UNCERTAINTY (extra scrutiny needed):**
61
+ ${uncertainties}
62
+ `;
63
+ }
64
+
65
+ messageText += `
66
+ **YOUR TASK:**
67
+ Each reviewer should focus on a different cross-cutting concern:
68
+
69
+ 1. **Scalability & Performance**
70
+ - Can this handle the stated workloads?
71
+ - Where are the bottlenecks?
72
+ - How does it scale (vertically/horizontally)?
73
+
74
+ 2. **Reliability & Failure Modes**
75
+ - What happens when components fail?
76
+ - Are there single points of failure?
77
+ - How is state handled during failures?
78
+
79
+ 3. **Operational Complexity**
80
+ - How hard is this to deploy, monitor, and debug?
81
+ - What operational burden does this create?
82
+ - How observable is the system?
83
+
84
+ 4. **Developer Experience**
85
+ - How easy is this to understand and modify?
86
+ - What's the learning curve?
87
+ - How testable is this design?
88
+
89
+ 5. **Cost Efficiency**
90
+ - What are the cost drivers?
91
+ - Are there cheaper alternatives that meet requirements?
92
+ - How do costs scale with load?
93
+
94
+ **For each concern:**
95
+ - Identify specific issues or risks
96
+ - Suggest improvements aligned with the stated priorities
97
+ - Note trade-offs (improving one area may hurt another)
98
+
99
+ Focus on actionable feedback, not generic advice.`;
100
+
101
+ return [
102
+ {
103
+ role: 'user',
104
+ content: {
105
+ type: 'text',
106
+ text: messageText,
107
+ },
108
+ },
109
+ ];
110
+ },
111
+ };
@@ -0,0 +1,80 @@
1
+ import { PromptDefinition } from './types.js';
2
+
3
+ /**
4
+ * Prompt to surface and challenge hidden assumptions in a plan or design.
5
+ */
6
+ export const assumptionsPrompt: PromptDefinition = {
7
+ name: 'assumptions',
8
+ description:
9
+ 'Surface and challenge hidden assumptions in a plan, design, or idea. Identifies implicit premises that could be risky if wrong.',
10
+ arguments: [
11
+ {
12
+ name: 'plan',
13
+ description: 'The plan, design, or idea to analyze for hidden assumptions',
14
+ required: true,
15
+ },
16
+ {
17
+ name: 'constraints',
18
+ description: 'Known hard constraints that are definitely true',
19
+ required: false,
20
+ },
21
+ {
22
+ name: 'concerns',
23
+ description: 'Areas where you feel uncertain or worried',
24
+ required: false,
25
+ },
26
+ ],
27
+ buildMessages: (args: Record<string, string>) => {
28
+ const { plan, constraints, concerns } = args;
29
+
30
+ if (!plan) {
31
+ throw new Error('plan argument is required');
32
+ }
33
+
34
+ let messageText = `Please analyze the hidden assumptions in this plan:
35
+
36
+ **PLAN/DESIGN/IDEA:**
37
+ ${plan}
38
+ `;
39
+
40
+ if (constraints) {
41
+ messageText += `
42
+ **KNOWN CONSTRAINTS (definitely true):**
43
+ ${constraints}
44
+ `;
45
+ }
46
+
47
+ if (concerns) {
48
+ messageText += `
49
+ **MY CONCERNS/UNCERTAINTIES:**
50
+ ${concerns}
51
+ `;
52
+ }
53
+
54
+ messageText += `
55
+ **YOUR TASK:**
56
+ Identify the implicit assumptions underlying this plan. For each assumption:
57
+
58
+ 1. **State it explicitly** - What is being assumed without being stated?
59
+ 2. **Criticality** (high/medium/low) - How important is this assumption to the plan's success?
60
+ 3. **Fragility** (high/medium/low) - How likely is this assumption to be wrong?
61
+ 4. **Validation** - How could we test or verify this assumption?
62
+
63
+ Focus on assumptions that:
64
+ - Are easy to overlook
65
+ - Would cause significant problems if wrong
66
+ - Others analyzing this might miss
67
+
68
+ Each LLM should try to find assumptions the others might not catch.`;
69
+
70
+ return [
71
+ {
72
+ role: 'user',
73
+ content: {
74
+ type: 'text',
75
+ text: messageText,
76
+ },
77
+ },
78
+ ];
79
+ },
80
+ };
@@ -0,0 +1,79 @@
1
+ import { PromptDefinition } from './types.js';
2
+
3
+ /**
4
+ * Prompt to hunt for missing considerations, gaps, and overlooked risks.
5
+ */
6
+ export const blindspotsPrompt: PromptDefinition = {
7
+ name: 'blindspots',
8
+ description:
9
+ 'Hunt for missing considerations, overlooked risks, and gaps in a proposal. Acts as a panel of critical reviewers looking for what might be underweighted.',
10
+ arguments: [
11
+ {
12
+ name: 'proposal',
13
+ description: 'The plan, code, design, or proposal to review for blindspots',
14
+ required: true,
15
+ },
16
+ {
17
+ name: 'covered',
18
+ description: 'What you think you have already addressed or considered',
19
+ required: false,
20
+ },
21
+ {
22
+ name: 'risk_tolerance',
23
+ description: 'Your risk tolerance level: low, medium, or high',
24
+ required: false,
25
+ },
26
+ ],
27
+ buildMessages: (args: Record<string, string>) => {
28
+ const { proposal, covered, risk_tolerance } = args;
29
+
30
+ if (!proposal) {
31
+ throw new Error('proposal argument is required');
32
+ }
33
+
34
+ let messageText = `Act as a panel of critical reviewers looking for blindspots.
35
+
36
+ **PROPOSAL TO REVIEW:**
37
+ ${proposal}
38
+ `;
39
+
40
+ if (covered) {
41
+ messageText += `
42
+ **ALREADY CONSIDERED:**
43
+ ${covered}
44
+ `;
45
+ }
46
+
47
+ if (risk_tolerance) {
48
+ messageText += `
49
+ **RISK TOLERANCE:** ${risk_tolerance}
50
+ `;
51
+ }
52
+
53
+ messageText += `
54
+ **YOUR TASK:**
55
+ Each reviewer should identify 2-3 potential blindspots:
56
+
57
+ 1. **Failure modes** - Ways this could fail that aren't being considered
58
+ 2. **Missing considerations** - Important factors that are overlooked
59
+ 3. **Edge cases** - Scenarios that might break assumptions
60
+ 4. **Dependencies** - External factors that could cause problems
61
+
62
+ For each blindspot:
63
+ - Be specific about WHAT the concern is
64
+ - Explain WHY it's concerning (impact if it happens)
65
+ - Suggest potential mitigations
66
+
67
+ Look for things that are easy to miss because they seem "obvious" or fall outside the immediate scope. Different reviewers should explore different angles.`;
68
+
69
+ return [
70
+ {
71
+ role: 'user',
72
+ content: {
73
+ type: 'text',
74
+ text: messageText,
75
+ },
76
+ },
77
+ ];
78
+ },
79
+ };
@@ -0,0 +1,92 @@
1
+ import { PromptDefinition } from './types.js';
2
+
3
+ /**
4
+ * Prompt for divergent exploration followed by convergence.
5
+ */
6
+ export const divergeConvergePrompt: PromptDefinition = {
7
+ name: 'diverge_converge',
8
+ description:
9
+ 'Structure divergent thinking (explore many options) followed by convergence (evaluate and select). Maximizes creative exploration before narrowing down.',
10
+ arguments: [
11
+ {
12
+ name: 'challenge',
13
+ description: 'The problem or challenge to solve',
14
+ required: true,
15
+ },
16
+ {
17
+ name: 'width',
18
+ description: 'Exploration width: "wild" for creative/unconventional, "focused" for practical',
19
+ required: false,
20
+ },
21
+ {
22
+ name: 'convergence_criteria',
23
+ description: 'What makes a solution "good" - criteria for evaluating options',
24
+ required: false,
25
+ },
26
+ ],
27
+ buildMessages: (args: Record<string, string>) => {
28
+ const { challenge, width, convergence_criteria } = args;
29
+
30
+ if (!challenge) {
31
+ throw new Error('challenge argument is required');
32
+ }
33
+
34
+ const explorationMode = width || 'balanced';
35
+ const criteria = convergence_criteria || 'feasibility, impact, and effort required';
36
+
37
+ let messageText = `Let's use divergent-then-convergent thinking:
38
+
39
+ **CHALLENGE:**
40
+ ${challenge}
41
+
42
+ **EXPLORATION MODE:** ${explorationMode}
43
+ **SUCCESS CRITERIA:** ${criteria}
44
+
45
+ ---
46
+
47
+ ## PHASE 1: DIVERGE
48
+
49
+ Each LLM should propose 2-3 **substantially DIFFERENT** approaches. The goal is diversity, not agreement.
50
+
51
+ Guidelines:
52
+ - Maximize variety in your proposals
53
+ - Include at least one unconventional or surprising idea
54
+ - Don't self-censor "crazy" ideas yet
55
+ - Brief descriptions are fine - we'll evaluate later
56
+ `;
57
+
58
+ if (explorationMode === 'wild') {
59
+ messageText += `- Push boundaries - what would you suggest if there were no constraints?
60
+ `;
61
+ } else if (explorationMode === 'focused') {
62
+ messageText += `- Stay practical - focus on implementable solutions
63
+ `;
64
+ }
65
+
66
+ messageText += `
67
+ ---
68
+
69
+ ## PHASE 2: CONVERGE
70
+
71
+ After all options are on the table, evaluate them against the success criteria:
72
+
73
+ 1. **Quick assessment** of each option against: ${criteria}
74
+ 2. **Identify top 2-3 candidates** that best meet the criteria
75
+ 3. **Hybrid opportunities** - can elements from different approaches be combined?
76
+ 4. **Recommendation** - which approach (or combination) should we pursue?
77
+
78
+ ---
79
+
80
+ Start with Phase 1 - generate diverse options first, then we'll converge.`;
81
+
82
+ return [
83
+ {
84
+ role: 'user',
85
+ content: {
86
+ type: 'text',
87
+ text: messageText,
88
+ },
89
+ },
90
+ ];
91
+ },
92
+ };