thumbgate 1.16.13 → 1.16.19

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 (62) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.well-known/mcp/server-card.json +1 -1
  4. package/README.md +3 -1
  5. package/adapters/claude/.mcp.json +2 -2
  6. package/adapters/mcp/server-stdio.js +26 -1
  7. package/adapters/opencode/opencode.json +1 -1
  8. package/bin/cli.js +420 -1
  9. package/config/gate-templates.json +372 -0
  10. package/config/mcp-allowlists.json +25 -0
  11. package/config/model-candidates.json +59 -2
  12. package/config/model-tiers.json +4 -1
  13. package/package.json +79 -22
  14. package/public/compare.html +6 -0
  15. package/public/index.html +144 -11
  16. package/public/numbers.html +8 -8
  17. package/public/pro.html +22 -24
  18. package/scripts/agent-design-governance.js +211 -0
  19. package/scripts/agent-reasoning-traces.js +683 -0
  20. package/scripts/agent-reward-model.js +438 -0
  21. package/scripts/agent-stack-survival-audit.js +231 -0
  22. package/scripts/ai-engineering-stack-guardrails.js +256 -0
  23. package/scripts/billing.js +16 -4
  24. package/scripts/chatgpt-ads-readiness-pack.js +195 -0
  25. package/scripts/cli-schema.js +277 -0
  26. package/scripts/code-graph-guardrails.js +176 -0
  27. package/scripts/deepseek-v4-runtime-guardrails.js +253 -0
  28. package/scripts/gemini-embedding-policy.js +198 -0
  29. package/scripts/inference-cache-policy.js +39 -0
  30. package/scripts/judge-reward-function.js +396 -0
  31. package/scripts/llm-behavior-monitor.js +251 -0
  32. package/scripts/long-running-agent-context-guardrails.js +176 -0
  33. package/scripts/multimodal-retrieval-plan.js +31 -11
  34. package/scripts/oss-pr-opportunity-scout.js +240 -0
  35. package/scripts/proactive-agent-eval-guardrails.js +230 -0
  36. package/scripts/profile-router.js +5 -4
  37. package/scripts/prompting-operating-system.js +273 -0
  38. package/scripts/proxy-pointer-rag-guardrails.js +189 -0
  39. package/scripts/rag-precision-guardrails.js +202 -0
  40. package/scripts/rate-limiter.js +1 -1
  41. package/scripts/reasoning-efficiency-guardrails.js +176 -0
  42. package/scripts/reward-hacking-guardrails.js +251 -0
  43. package/scripts/seo-gsd.js +1201 -11
  44. package/scripts/single-use-credential-gate.js +182 -0
  45. package/scripts/structured-prompt-driven.js +226 -0
  46. package/scripts/telemetry-analytics.js +31 -6
  47. package/scripts/tool-registry.js +92 -0
  48. package/scripts/upstream-contribution-engine.js +379 -0
  49. package/scripts/vector-store.js +119 -4
  50. package/src/api/server.js +333 -100
  51. package/scripts/agents-sdk-sandbox-plan.js +0 -57
  52. package/scripts/ai-org-governance.js +0 -98
  53. package/scripts/artifact-agent-plan.js +0 -81
  54. package/scripts/enterprise-agent-rollout.js +0 -34
  55. package/scripts/experience-replay-governance.js +0 -69
  56. package/scripts/inference-economics.js +0 -53
  57. package/scripts/knowledge-layer-plan.js +0 -108
  58. package/scripts/memory-store-governance.js +0 -60
  59. package/scripts/post-training-governance.js +0 -34
  60. package/scripts/production-agent-readiness.js +0 -40
  61. package/scripts/scaling-law-claims.js +0 -60
  62. package/scripts/student-consistent-training.js +0 -73
@@ -0,0 +1,230 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+
7
+ const SOURCE = Object.freeze({
8
+ postUrl: 'https://x.com/dair_ai/status/2048083882327916688',
9
+ paperUrl: 'https://arxiv.org/abs/2604.00842',
10
+ title: 'Proactive Agent Research Environment: Simulating Active Users to Evaluate Proactive Assistants',
11
+ arxivId: '2604.00842',
12
+ submitted: '2026-04-01',
13
+ postCreatedAt: '2026-04-25T16:57:03.000Z',
14
+ });
15
+
16
+ function parseNumber(value, fallback = 0) {
17
+ const parsed = Number(value);
18
+ return Number.isFinite(parsed) ? parsed : fallback;
19
+ }
20
+
21
+ function parseBoolean(value, fallback = false) {
22
+ if (value === undefined || value === null || value === '') return fallback;
23
+ if (typeof value === 'boolean') return value;
24
+ return /^(1|true|yes|on)$/i.test(String(value).trim());
25
+ }
26
+
27
+ function splitList(value) {
28
+ if (Array.isArray(value)) return value.map(String).map((item) => item.trim()).filter(Boolean);
29
+ return String(value || '').split(',').map((item) => item.trim()).filter(Boolean);
30
+ }
31
+
32
+ function normalizeOptions(raw = {}) {
33
+ return {
34
+ workflow: String(raw.workflow || raw.name || 'proactive agent workflow').trim() || 'proactive agent workflow',
35
+ apps: splitList(raw.apps || raw.applications),
36
+ states: splitList(raw.states || raw['app-states']),
37
+ stateCount: parseNumber(raw['state-count'] || raw.stateCount || splitList(raw.states).length, splitList(raw.states).length),
38
+ actionCount: parseNumber(raw['action-count'] || raw.actionCount, 0),
39
+ taskCount: parseNumber(raw['task-count'] || raw.taskCount, 0),
40
+ hasStateMachine: parseBoolean(raw['state-machine'] || raw.hasStateMachine, false),
41
+ hasActiveUserSimulation: parseBoolean(raw['active-user-simulation'] || raw.hasActiveUserSimulation, false),
42
+ hasGoalInferenceEvals: parseBoolean(raw['goal-inference-evals'] || raw.hasGoalInferenceEvals, false),
43
+ hasInterventionTimingEvals: parseBoolean(raw['intervention-timing-evals'] || raw.hasInterventionTimingEvals, false),
44
+ hasMultiAppEvals: parseBoolean(raw['multi-app-evals'] || raw.hasMultiAppEvals, false),
45
+ flatToolApiOnly: parseBoolean(raw['flat-tool-api-only'] || raw.flatToolApiOnly, false),
46
+ proactiveWrites: parseBoolean(raw['proactive-writes'] || raw.proactiveWrites, false),
47
+ userVisibleActions: parseBoolean(raw['user-visible-actions'] || raw.userVisibleActions, false),
48
+ };
49
+ }
50
+
51
+ function buildSignals(options) {
52
+ const signals = [];
53
+ if (!options.hasStateMachine || options.flatToolApiOnly) {
54
+ signals.push({
55
+ id: 'flat_tool_api_gap',
56
+ severity: 'high',
57
+ message: 'Flat tool APIs miss stateful navigation and state-dependent action spaces.',
58
+ gate: 'Require finite-state app model before proactive execution.',
59
+ });
60
+ }
61
+ if (!options.hasActiveUserSimulation) {
62
+ signals.push({
63
+ id: 'missing_active_user_simulation',
64
+ severity: 'high',
65
+ message: 'Proactive agents need simulated user progress before timing can be evaluated.',
66
+ gate: 'Run active user simulation before enabling anticipatory actions.',
67
+ });
68
+ }
69
+ if (!options.hasGoalInferenceEvals) {
70
+ signals.push({
71
+ id: 'missing_goal_inference_eval',
72
+ severity: 'medium',
73
+ message: 'The agent may intervene without evidence that it inferred the user goal correctly.',
74
+ gate: 'Grade goal inference before intervention approval.',
75
+ });
76
+ }
77
+ if (!options.hasInterventionTimingEvals) {
78
+ signals.push({
79
+ id: 'missing_intervention_timing_eval',
80
+ severity: 'high',
81
+ message: 'A helpful action at the wrong time becomes interruption or damage.',
82
+ gate: 'Require too-early, on-time, and too-late timing eval cases.',
83
+ });
84
+ }
85
+ if ((options.apps.length > 1 || options.hasMultiAppEvals === false) && options.proactiveWrites) {
86
+ signals.push({
87
+ id: 'multi_app_write_risk',
88
+ severity: 'critical',
89
+ message: 'Multi-app proactive writes can compound state mistakes across tools.',
90
+ gate: 'Block multi-app proactive writes until orchestration evals and rollback evidence exist.',
91
+ });
92
+ }
93
+ if (options.userVisibleActions && !options.hasInterventionTimingEvals) {
94
+ signals.push({
95
+ id: 'user_visible_interruption_risk',
96
+ severity: 'high',
97
+ message: 'User-visible interventions need timing proof before notification, scheduling, or communication actions.',
98
+ gate: 'Require intervention timing proof before user-visible actions.',
99
+ });
100
+ }
101
+ return signals;
102
+ }
103
+
104
+ function buildMetrics(options) {
105
+ return [
106
+ { id: 'goal_inference_accuracy', target: '>= 0.85', required: true },
107
+ { id: 'intervention_timing_f1', target: '>= 0.80', required: true },
108
+ { id: 'false_intervention_rate', target: '<= 0.05', required: true },
109
+ { id: 'state_transition_validity', target: '>= 0.98', required: true },
110
+ { id: 'multi_app_orchestration_success', target: options.apps.length > 1 ? '>= 0.85' : 'optional', required: options.apps.length > 1 },
111
+ ];
112
+ }
113
+
114
+ function buildProactiveAgentEvalGuardrailsPlan(rawOptions = {}) {
115
+ const options = normalizeOptions(rawOptions);
116
+ const signals = buildSignals(options);
117
+ const critical = signals.filter((signal) => signal.severity === 'critical').length;
118
+ const high = signals.filter((signal) => signal.severity === 'high').length;
119
+
120
+ return {
121
+ name: 'thumbgate-proactive-agent-eval-guardrails',
122
+ source: SOURCE,
123
+ workflow: options.workflow,
124
+ status: critical > 0 ? 'blocked' : high > 0 ? 'needs_eval' : 'ready',
125
+ summary: {
126
+ signalCount: signals.length,
127
+ critical,
128
+ high,
129
+ apps: options.apps,
130
+ stateCount: options.stateCount,
131
+ actionCount: options.actionCount,
132
+ taskCount: options.taskCount,
133
+ },
134
+ pareMapping: {
135
+ appModel: options.hasStateMachine ? 'finite_state_machine_present' : 'finite_state_machine_required',
136
+ userSimulation: options.hasActiveUserSimulation ? 'active_user_simulation_present' : 'active_user_simulation_required',
137
+ actionSpace: 'state-dependent action spaces should be explicit per app state',
138
+ evaluationAxes: [
139
+ 'context observation',
140
+ 'goal inference',
141
+ 'intervention timing',
142
+ 'multi-app orchestration',
143
+ ],
144
+ },
145
+ signals,
146
+ metrics: buildMetrics(options),
147
+ gates: signals.map((signal) => ({
148
+ id: signal.id,
149
+ action: signal.severity === 'critical' ? 'block' : 'warn',
150
+ message: signal.gate,
151
+ })),
152
+ nextActions: [
153
+ 'Model each app as states, allowed actions, and valid transitions before judging proactive behavior.',
154
+ 'Add active user simulation cases where the user keeps navigating while the agent observes.',
155
+ 'Evaluate goal inference separately from intervention timing so a correct goal at the wrong time is still caught.',
156
+ 'Block proactive writes across multiple apps until orchestration success and rollback evidence are measured.',
157
+ 'Attach the eval report to any claim that a proactive agent is production-ready.',
158
+ ],
159
+ marketingAngle: {
160
+ headline: 'Proactive agents need stateful eval gates.',
161
+ subhead: 'PARE shows why flat tool-call benchmarks miss real app behavior. ThumbGate turns those stateful eval failures into pre-action gates before a proactive assistant interrupts users or writes across apps.',
162
+ replyDraft: 'This is the missing eval shape for proactive agents. Flat tool calls cannot tell whether the agent acted at the right state or the right time. ThumbGate can use this pattern as the enforcement layer: stateful eval failure -> pre-action gate before the next proactive write.',
163
+ },
164
+ };
165
+ }
166
+
167
+ function formatProactiveAgentEvalGuardrailsPlan(report) {
168
+ const lines = [
169
+ '',
170
+ 'ThumbGate Proactive Agent Eval Guardrails',
171
+ '-'.repeat(43),
172
+ `Workflow : ${report.workflow}`,
173
+ `Status : ${report.status}`,
174
+ `Source : ${report.source.paperUrl}`,
175
+ `Signals : ${report.summary.signalCount}`,
176
+ ];
177
+ if (report.signals.length > 0) {
178
+ lines.push('', 'Signals:');
179
+ for (const signal of report.signals) {
180
+ lines.push(` - [${signal.severity}] ${signal.id}: ${signal.message}`);
181
+ lines.push(` Gate: ${signal.gate}`);
182
+ }
183
+ }
184
+ lines.push('', 'Required metrics:');
185
+ for (const metric of report.metrics) {
186
+ lines.push(` - ${metric.id}: ${metric.target}${metric.required ? ' (required)' : ''}`);
187
+ }
188
+ lines.push('', 'Next actions:');
189
+ for (const action of report.nextActions) lines.push(` - ${action}`);
190
+ lines.push('', `Reply draft: ${report.marketingAngle.replyDraft}`, '');
191
+ return `${lines.join('\n')}\n`;
192
+ }
193
+
194
+ function writeProactiveAgentEvalPromoPack(outputDir = path.join(__dirname, '..', 'docs', 'marketing')) {
195
+ const report = buildProactiveAgentEvalGuardrailsPlan({
196
+ workflow: 'proactive assistant shipping checklist',
197
+ apps: ['calendar', 'email', 'tasks'],
198
+ 'state-count': 12,
199
+ 'action-count': 24,
200
+ 'task-count': 143,
201
+ 'flat-tool-api-only': true,
202
+ 'proactive-writes': true,
203
+ 'user-visible-actions': true,
204
+ });
205
+ fs.mkdirSync(outputDir, { recursive: true });
206
+ const jsonPath = path.join(outputDir, 'dair-pare-proactive-agent-pack.json');
207
+ const markdownPath = path.join(outputDir, 'dair-pare-proactive-agent-pack.md');
208
+ fs.writeFileSync(jsonPath, `${JSON.stringify(report, null, 2)}\n`);
209
+ fs.writeFileSync(markdownPath, formatProactiveAgentEvalGuardrailsPlan(report));
210
+ return { report, jsonPath, markdownPath };
211
+ }
212
+
213
+ module.exports = {
214
+ SOURCE,
215
+ buildMetrics,
216
+ buildProactiveAgentEvalGuardrailsPlan,
217
+ buildSignals,
218
+ formatProactiveAgentEvalGuardrailsPlan,
219
+ normalizeOptions,
220
+ writeProactiveAgentEvalPromoPack,
221
+ };
222
+
223
+ function isCliInvocation(argv = process.argv) {
224
+ return Boolean(argv[1] && path.resolve(argv[1]) === __filename);
225
+ }
226
+
227
+ if (isCliInvocation()) {
228
+ const { jsonPath, markdownPath } = writeProactiveAgentEvalPromoPack();
229
+ console.log(JSON.stringify({ jsonPath, markdownPath }, null, 2));
230
+ }
@@ -125,14 +125,15 @@ function findMostRestrictiveProfile(toolName) {
125
125
  if (!policy || !policy.profiles) return null;
126
126
  const profileRank = new Map(PROFILE_RESTRICTIVENESS_ORDER.map((name, index) => [name, index]));
127
127
 
128
- // Sort profiles by number of tools (most restrictive first)
128
+ // Sort by named least-privilege order first. Some specialized profiles
129
+ // expose fewer tools than locked but carry stronger side-effect authority.
129
130
  const candidates = Object.entries(policy.profiles)
130
131
  .filter(([, tools]) => tools.includes(toolName))
131
132
  .sort((a, b) => {
132
- const sizeDelta = a[1].length - b[1].length;
133
- if (sizeDelta !== 0) return sizeDelta;
134
- return (profileRank.get(a[0]) ?? Number.MAX_SAFE_INTEGER)
133
+ const rankDelta = (profileRank.get(a[0]) ?? Number.MAX_SAFE_INTEGER)
135
134
  - (profileRank.get(b[0]) ?? Number.MAX_SAFE_INTEGER);
135
+ if (rankDelta !== 0) return rankDelta;
136
+ return a[1].length - b[1].length;
136
137
  });
137
138
 
138
139
  if (candidates.length === 0) return null;
@@ -0,0 +1,273 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ /**
5
+ * Prompting Operating System
6
+ *
7
+ * Converts modern "AI power user" prompting guidance into ThumbGate pre-action
8
+ * planning: choose the run mode, gather the right context, set reasoning
9
+ * budget, route tools, and attach trust checks before an agent acts.
10
+ */
11
+
12
+ const path = require('node:path');
13
+
14
+ const MODE_RULES = [
15
+ {
16
+ mode: 'deep-research',
17
+ pattern: /\b(research|report|compare|market|latest|sources?|citations?|well-researched)\b/i,
18
+ reasoningBudget: 'deep',
19
+ tools: ['web-search', 'source-capture', 'citation-check'],
20
+ contextRequirements: ['question', 'source scope', 'recency requirement'],
21
+ },
22
+ {
23
+ mode: 'decision-support',
24
+ pattern: /\b(decide|choose|buy|job|career|study|hire|pricing|strategy|important decision)\b/i,
25
+ reasoningBudget: 'minutes',
26
+ tools: ['tradeoff-table', 'risk-check', 'evidence-check'],
27
+ contextRequirements: ['decision criteria', 'constraints', 'stakes', 'alternatives'],
28
+ },
29
+ {
30
+ mode: 'build',
31
+ pattern: /\b(build|implement|code|website|game|app|fix|ship)\b/i,
32
+ reasoningBudget: 'standard',
33
+ tools: ['repo-inspection', 'code-edit', 'tests'],
34
+ contextRequirements: ['target files', 'acceptance criteria', 'verification command'],
35
+ },
36
+ {
37
+ mode: 'data-analysis',
38
+ pattern: /\b(analyze data|spreadsheet|csv|xlsx|chart|visuali[sz]e|dataset)\b/i,
39
+ reasoningBudget: 'standard',
40
+ tools: ['data-parser', 'charting', 'sanity-check'],
41
+ contextRequirements: ['data file', 'analysis question', 'metric definitions'],
42
+ },
43
+ {
44
+ mode: 'visual-generation',
45
+ pattern: /\b(image|photo|diagram|visual|mockup|poster|thumbnail)\b/i,
46
+ reasoningBudget: 'standard',
47
+ tools: ['image-generation', 'visual-qa'],
48
+ contextRequirements: ['visual goal', 'style direction', 'dimensions'],
49
+ },
50
+ ];
51
+
52
+ const DEFAULT_MODE = {
53
+ mode: 'quick-answer',
54
+ reasoningBudget: 'fast',
55
+ tools: ['direct-answer'],
56
+ contextRequirements: ['question'],
57
+ };
58
+
59
+ function planPromptingRun(input = {}) {
60
+ const request = String(input.request || input.prompt || '').trim();
61
+ const attachments = Array.isArray(input.attachments) ? input.attachments : [];
62
+ const rule = MODE_RULES.find((candidate) => candidate.pattern.test(request)) || DEFAULT_MODE;
63
+ const attachmentContext = inferAttachmentContext(attachments);
64
+ const contextRequirements = Array.from(new Set([
65
+ ...rule.contextRequirements,
66
+ ...attachmentContext.requirements,
67
+ ]));
68
+ const providedContext = inferProvidedContext(request, attachments);
69
+ const missingContext = contextRequirements.filter((item) => !providedContext.includes(item));
70
+ const trustChecks = buildTrustChecks(rule.mode, input);
71
+
72
+ return {
73
+ mode: rule.mode,
74
+ reasoningBudget: rule.reasoningBudget,
75
+ tools: Array.from(new Set([...rule.tools, ...attachmentContext.tools])),
76
+ contextRequirements,
77
+ providedContext,
78
+ missingContext,
79
+ trustChecks,
80
+ gates: buildPromptGates({ mode: rule.mode, missingContext, trustChecks, input }),
81
+ promptTemplate: buildPromptTemplate({ mode: rule.mode, request, contextRequirements, trustChecks }),
82
+ };
83
+ }
84
+
85
+ function evaluatePromptReadiness(plan = {}) {
86
+ const hardBlocks = (plan.gates || []).filter((gate) => gate.severity === 'block');
87
+ const warnings = (plan.gates || []).filter((gate) => gate.severity === 'warn');
88
+ return {
89
+ allowed: hardBlocks.length === 0,
90
+ score: Math.max(0, 100 - (hardBlocks.length * 35) - (warnings.length * 10) - ((plan.missingContext || []).length * 8)),
91
+ hardBlocks,
92
+ warnings,
93
+ recommendation: promptReadinessRecommendation(hardBlocks, warnings),
94
+ };
95
+ }
96
+
97
+ function promptReadinessRecommendation(hardBlocks, warnings) {
98
+ if (hardBlocks.length) return 'Collect missing high-stakes context before running the agent.';
99
+ if (warnings.length) return 'Proceed with explicit uncertainty and evidence capture.';
100
+ return 'Prompt is ready for execution.';
101
+ }
102
+
103
+ function inferAttachmentContext(attachments = []) {
104
+ const requirements = [];
105
+ const tools = [];
106
+ for (const attachment of attachments) {
107
+ const name = String(attachment.name || attachment.path || attachment.type || '').toLowerCase();
108
+ if (/\.(png|jpg|jpeg|webp|gif)$|image/.test(name)) {
109
+ requirements.push('image context');
110
+ tools.push('vision');
111
+ }
112
+ if (/\.(csv|tsv|xlsx|xls)$|spreadsheet|dataset/.test(name)) {
113
+ requirements.push('data file');
114
+ tools.push('data-parser');
115
+ }
116
+ if (/\.(pdf|docx|md|txt)$|document/.test(name)) {
117
+ requirements.push('document context');
118
+ tools.push('document-parser');
119
+ }
120
+ }
121
+ return { requirements, tools };
122
+ }
123
+
124
+ function inferProvidedContext(request, attachments = []) {
125
+ const provided = new Set();
126
+ if (request) provided.add('question');
127
+ if (/\b(criteria|must|need|constraint|budget|deadline)\b/i.test(request)) provided.add('constraints');
128
+ if (/\b(option|alternative|versus|vs\.?|compare)\b/i.test(request)) provided.add('alternatives');
129
+ if (/\b(source|cite|link|latest|2026|today|yesterday)\b/i.test(request)) {
130
+ provided.add('source scope');
131
+ provided.add('recency requirement');
132
+ }
133
+ if (/\b(test|verify|acceptance|done when)\b/i.test(request)) provided.add('verification command');
134
+ if (/\b(file|path|component|script|module)\b/i.test(request) || hasPathLikeTarget(request)) {
135
+ provided.add('target files');
136
+ }
137
+ if (/\b(metric|kpi|revenue|conversion|score)\b/i.test(request)) provided.add('metric definitions');
138
+ if (attachments.length > 0) {
139
+ provided.add('document context');
140
+ provided.add('image context');
141
+ provided.add('data file');
142
+ }
143
+ return Array.from(provided);
144
+ }
145
+
146
+ function hasPathLikeTarget(request = '') {
147
+ return String(request)
148
+ .split(/\s+/)
149
+ .map(stripPathPunctuation)
150
+ .some((part) => part.includes('/') && part.includes('.') && isSafePathToken(part));
151
+ }
152
+
153
+ function stripPathPunctuation(part) {
154
+ let text = String(part);
155
+ while (text && '("\''.includes(text[0])) text = text.slice(1);
156
+ while (text && '),.\'"'.includes(text.at(-1))) text = text.slice(0, -1);
157
+ return text;
158
+ }
159
+
160
+ function isSafePathToken(part) {
161
+ return String(part).split('').every((char) => {
162
+ const code = char.charCodeAt(0);
163
+ return char === '/' || char === '.' || char === '-' || char === '_' ||
164
+ (code >= 48 && code <= 57) ||
165
+ (code >= 65 && code <= 90) ||
166
+ (code >= 97 && code <= 122);
167
+ });
168
+ }
169
+
170
+ function buildTrustChecks(mode, input = {}) {
171
+ const checks = [
172
+ 'state assumptions explicitly',
173
+ 'capture evidence before completion claim',
174
+ 'mark uncertainty when source quality is weak',
175
+ ];
176
+ if (mode === 'deep-research') checks.push('cite primary or authoritative sources', 'compare publication dates');
177
+ if (mode === 'decision-support') checks.push('show tradeoffs and downside risk', 'separate reversible from irreversible choices');
178
+ if (mode === 'build') checks.push('inspect code before editing', 'run focused tests');
179
+ if (mode === 'data-analysis') checks.push('validate row counts and missing values', 'avoid unsupported causal claims');
180
+ if (input.highStakes) checks.push('escalate high-stakes claims for verification');
181
+ return checks;
182
+ }
183
+
184
+ function buildPromptGates({ mode, missingContext, trustChecks, input }) {
185
+ const gates = [];
186
+ const highStakes = Boolean(input.highStakes || ['decision-support'].includes(mode));
187
+ if (highStakes && missingContext.length > 0) {
188
+ gates.push({
189
+ id: 'missing-high-stakes-context',
190
+ severity: 'block',
191
+ reason: `Missing context for high-stakes ${mode}: ${missingContext.join(', ')}`,
192
+ });
193
+ }
194
+ if (missingContext.length > 0) {
195
+ gates.push({
196
+ id: 'missing-context-warning',
197
+ severity: 'warn',
198
+ reason: `Missing context may reduce answer quality: ${missingContext.join(', ')}`,
199
+ });
200
+ }
201
+ if (trustChecks.includes('capture evidence before completion claim')) {
202
+ gates.push({
203
+ id: 'evidence-before-claim',
204
+ severity: 'warn',
205
+ reason: 'Do not claim completion without evidence.',
206
+ });
207
+ }
208
+ return gates;
209
+ }
210
+
211
+ function buildPromptTemplate({ mode, request, contextRequirements, trustChecks }) {
212
+ return [
213
+ `Mode: ${mode}`,
214
+ `Task: ${request || '<task>'}`,
215
+ `Context to provide: ${contextRequirements.join(', ')}`,
216
+ `Trust checks: ${trustChecks.join('; ')}`,
217
+ 'Output: answer with evidence, assumptions, and next action.',
218
+ ].join('\n');
219
+ }
220
+
221
+ function formatPromptingPlan(plan = {}) {
222
+ return [
223
+ '# Prompting Operating Plan',
224
+ '',
225
+ `Mode: ${plan.mode}`,
226
+ `Reasoning budget: ${plan.reasoningBudget}`,
227
+ `Tools: ${(plan.tools || []).join(', ')}`,
228
+ `Missing context: ${(plan.missingContext || []).join(', ') || 'none'}`,
229
+ '',
230
+ '## Gates',
231
+ '',
232
+ ...(plan.gates || []).map((gate) => `- ${gate.severity}: ${gate.id} — ${gate.reason}`),
233
+ '',
234
+ '## Prompt Template',
235
+ '',
236
+ '```text',
237
+ plan.promptTemplate || '',
238
+ '```',
239
+ '',
240
+ ].join('\n');
241
+ }
242
+
243
+ function parseArgs(argv = process.argv.slice(2)) {
244
+ const args = { command: argv[0] || 'plan', request: '' };
245
+ for (const arg of argv.slice(1)) {
246
+ if (arg.startsWith('--request=')) args.request = arg.slice('--request='.length);
247
+ if (arg === '--high-stakes') args.highStakes = true;
248
+ }
249
+ return args;
250
+ }
251
+
252
+ function isCliInvocation(argv = process.argv) {
253
+ return Boolean(argv[1] && path.resolve(argv[1]) === __filename);
254
+ }
255
+
256
+ if (isCliInvocation()) {
257
+ const args = parseArgs();
258
+ const plan = planPromptingRun(args);
259
+ if (args.command === 'json') {
260
+ console.log(JSON.stringify({ plan, readiness: evaluatePromptReadiness(plan) }, null, 2));
261
+ } else if (args.command === 'plan') {
262
+ console.log(formatPromptingPlan(plan));
263
+ } else {
264
+ console.error(`Unknown command: ${args.command}. Use: plan, json`);
265
+ process.exit(1);
266
+ }
267
+ }
268
+
269
+ module.exports = {
270
+ evaluatePromptReadiness,
271
+ formatPromptingPlan,
272
+ planPromptingRun,
273
+ };