tachibot-mcp 2.0.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.
- package/.env.example +260 -0
- package/CHANGELOG.md +54 -0
- package/CODE_OF_CONDUCT.md +56 -0
- package/CONTRIBUTING.md +54 -0
- package/Dockerfile +36 -0
- package/LICENSE +644 -0
- package/README.md +201 -0
- package/SECURITY.md +95 -0
- package/dist/personality/komaai-expressions.js +12 -0
- package/dist/profiles/balanced.json +33 -0
- package/dist/profiles/code_focus.json +33 -0
- package/dist/profiles/full.json +33 -0
- package/dist/profiles/minimal.json +33 -0
- package/dist/profiles/research_power.json +33 -0
- package/dist/scripts/build-profiles.js +46 -0
- package/dist/src/application/services/focus/FocusModeRegistry.js +46 -0
- package/dist/src/application/services/focus/FocusTool.service.js +109 -0
- package/dist/src/application/services/focus/ModeRegistry.js +46 -0
- package/dist/src/application/services/focus/modes/focus-deep.mode.js +27 -0
- package/dist/src/application/services/focus/modes/status.mode.js +50 -0
- package/dist/src/application/services/focus/modes/tachibot-status.mode.js +50 -0
- package/dist/src/collaborative-orchestrator.js +391 -0
- package/dist/src/config/model-constants.js +188 -0
- package/dist/src/config/model-defaults.js +57 -0
- package/dist/src/config/model-preferences.js +382 -0
- package/dist/src/config/timeout-config.js +130 -0
- package/dist/src/config.js +173 -0
- package/dist/src/domain/interfaces/IFocusMode.js +5 -0
- package/dist/src/domain/interfaces/IProvider.js +6 -0
- package/dist/src/domain/interfaces/ITool.js +5 -0
- package/dist/src/focus-deep.js +245 -0
- package/dist/src/infrastructure/ascii/art/robots.ascii.js +16 -0
- package/dist/src/mcp-client.js +90 -0
- package/dist/src/memory/index.js +17 -0
- package/dist/src/memory/memory-config.js +135 -0
- package/dist/src/memory/memory-interface.js +174 -0
- package/dist/src/memory/memory-manager.js +383 -0
- package/dist/src/memory/providers/devlog-provider.js +385 -0
- package/dist/src/memory/providers/hybrid-provider.js +399 -0
- package/dist/src/memory/providers/local-provider.js +388 -0
- package/dist/src/memory/providers/mem0-provider.js +337 -0
- package/dist/src/modes/architect.js +477 -0
- package/dist/src/modes/auditor.js +362 -0
- package/dist/src/modes/challenger.js +841 -0
- package/dist/src/modes/code-reviewer.js +382 -0
- package/dist/src/modes/commit-guardian.js +424 -0
- package/dist/src/modes/documentation-writer.js +572 -0
- package/dist/src/modes/scout.js +587 -0
- package/dist/src/modes/shared/helpers/challenger-helpers.js +454 -0
- package/dist/src/modes/shared/helpers/index.js +17 -0
- package/dist/src/modes/shared/helpers/scout-helpers.js +270 -0
- package/dist/src/modes/shared/helpers/verifier-helpers.js +332 -0
- package/dist/src/modes/test-architect.js +767 -0
- package/dist/src/modes/verifier.js +378 -0
- package/dist/src/monitoring/performance-monitor.js +435 -0
- package/dist/src/optimization/batch-executor.js +121 -0
- package/dist/src/optimization/context-pruner.js +196 -0
- package/dist/src/optimization/cost-monitor.js +338 -0
- package/dist/src/optimization/index.js +65 -0
- package/dist/src/optimization/model-router.js +264 -0
- package/dist/src/optimization/result-cache.js +114 -0
- package/dist/src/optimization/token-optimizer.js +257 -0
- package/dist/src/optimization/token-tracker.js +118 -0
- package/dist/src/orchestrator-instructions.js +128 -0
- package/dist/src/orchestrator-lite.js +139 -0
- package/dist/src/orchestrator.js +191 -0
- package/dist/src/orchestrators/collaborative/interfaces/IToolExecutionEngine.js +1 -0
- package/dist/src/orchestrators/collaborative/interfaces/IToolExecutionStrategy.js +5 -0
- package/dist/src/orchestrators/collaborative/interfaces/IVisualizationRenderer.js +1 -0
- package/dist/src/orchestrators/collaborative/registries/ModelProviderRegistry.js +95 -0
- package/dist/src/orchestrators/collaborative/registries/ToolAdapterRegistry.js +64 -0
- package/dist/src/orchestrators/collaborative/services/tool-execution/ToolExecutionService.js +502 -0
- package/dist/src/orchestrators/collaborative/services/visualization/VisualizationService.js +206 -0
- package/dist/src/orchestrators/collaborative/types/session-types.js +5 -0
- package/dist/src/profiles/balanced.js +37 -0
- package/dist/src/profiles/code_focus.js +37 -0
- package/dist/src/profiles/debug_intensive.js +59 -0
- package/dist/src/profiles/full.js +37 -0
- package/dist/src/profiles/minimal.js +37 -0
- package/dist/src/profiles/research_code.js +59 -0
- package/dist/src/profiles/research_power.js +37 -0
- package/dist/src/profiles/types.js +5 -0
- package/dist/src/profiles/workflow_builder.js +53 -0
- package/dist/src/prompt-engineer-lite.js +78 -0
- package/dist/src/prompt-engineer.js +399 -0
- package/dist/src/reasoning-chain.js +508 -0
- package/dist/src/sequential-thinking.js +291 -0
- package/dist/src/server-diagnostic.js +74 -0
- package/dist/src/server-raw.js +158 -0
- package/dist/src/server-simple.js +58 -0
- package/dist/src/server.js +514 -0
- package/dist/src/session/session-logger.js +617 -0
- package/dist/src/session/session-manager.js +571 -0
- package/dist/src/session/session-tools.js +400 -0
- package/dist/src/tools/advanced-modes.js +200 -0
- package/dist/src/tools/claude-integration.js +356 -0
- package/dist/src/tools/consolidated/ai-router.js +174 -0
- package/dist/src/tools/consolidated/ai-tool.js +48 -0
- package/dist/src/tools/consolidated/brainstorm-tool.js +87 -0
- package/dist/src/tools/consolidated/environment-detector.js +80 -0
- package/dist/src/tools/consolidated/index.js +50 -0
- package/dist/src/tools/consolidated/search-tool.js +110 -0
- package/dist/src/tools/consolidated/workflow-tool.js +238 -0
- package/dist/src/tools/gemini-tools.js +329 -0
- package/dist/src/tools/grok-enhanced.js +376 -0
- package/dist/src/tools/grok-tools.js +299 -0
- package/dist/src/tools/lmstudio-tools.js +223 -0
- package/dist/src/tools/openai-tools.js +498 -0
- package/dist/src/tools/openrouter-tools.js +317 -0
- package/dist/src/tools/optimized-wrapper.js +204 -0
- package/dist/src/tools/perplexity-tools.js +294 -0
- package/dist/src/tools/pingpong-tool.js +343 -0
- package/dist/src/tools/qwen-wrapper.js +74 -0
- package/dist/src/tools/tool-router.js +444 -0
- package/dist/src/tools/unified-ai-provider.js +260 -0
- package/dist/src/tools/workflow-runner.js +425 -0
- package/dist/src/tools/workflow-validator-tool.js +107 -0
- package/dist/src/types.js +23 -0
- package/dist/src/utils/input-validator.js +130 -0
- package/dist/src/utils/model-router.js +91 -0
- package/dist/src/utils/progress-stream.js +255 -0
- package/dist/src/utils/provider-router.js +88 -0
- package/dist/src/utils/smart-api-client.js +146 -0
- package/dist/src/utils/table-builder.js +218 -0
- package/dist/src/utils/timestamp-formatter.js +134 -0
- package/dist/src/utils/tool-compressor.js +257 -0
- package/dist/src/utils/tool-config.js +201 -0
- package/dist/src/validators/dependency-graph-validator.js +147 -0
- package/dist/src/validators/interpolation-validator.js +222 -0
- package/dist/src/validators/output-usage-validator.js +151 -0
- package/dist/src/validators/syntax-validator.js +102 -0
- package/dist/src/validators/tool-registry-validator.js +123 -0
- package/dist/src/validators/tool-types.js +97 -0
- package/dist/src/validators/types.js +8 -0
- package/dist/src/validators/workflow-validator.js +134 -0
- package/dist/src/visualizer-lite.js +42 -0
- package/dist/src/visualizer.js +179 -0
- package/dist/src/workflows/circuit-breaker.js +199 -0
- package/dist/src/workflows/custom-workflows.js +451 -0
- package/dist/src/workflows/engine/AutoSynthesizer.js +97 -0
- package/dist/src/workflows/engine/StepParameterResolver.js +74 -0
- package/dist/src/workflows/engine/VariableInterpolator.js +123 -0
- package/dist/src/workflows/engine/WorkflowDiscovery.js +125 -0
- package/dist/src/workflows/engine/WorkflowExecutionEngine.js +485 -0
- package/dist/src/workflows/engine/WorkflowExecutor.js +113 -0
- package/dist/src/workflows/engine/WorkflowFileManager.js +244 -0
- package/dist/src/workflows/engine/WorkflowHelpers.js +114 -0
- package/dist/src/workflows/engine/WorkflowOutputFormatter.js +83 -0
- package/dist/src/workflows/engine/events/WorkflowEventBus.js +132 -0
- package/dist/src/workflows/engine/events/interfaces/IEventBus.js +5 -0
- package/dist/src/workflows/engine/handlers/ErrorRecoveryHandler.js +162 -0
- package/dist/src/workflows/engine/handlers/PromptEnhancementHandler.js +115 -0
- package/dist/src/workflows/engine/handlers/SessionPersistenceHandler.js +167 -0
- package/dist/src/workflows/engine/handlers/StepExecutionHandler.js +231 -0
- package/dist/src/workflows/engine/handlers/ToolInvocationHandler.js +46 -0
- package/dist/src/workflows/engine/interfaces/IAutoSynthesizer.js +5 -0
- package/dist/src/workflows/engine/interfaces/IStepParameterResolver.js +5 -0
- package/dist/src/workflows/engine/interfaces/IVariableInterpolator.js +5 -0
- package/dist/src/workflows/engine/interfaces/IWorkflowDiscovery.js +4 -0
- package/dist/src/workflows/engine/interfaces/IWorkflowFileManager.js +5 -0
- package/dist/src/workflows/engine/interfaces/IWorkflowOutputFormatter.js +5 -0
- package/dist/src/workflows/engine/state/WorkflowStateMachine.js +194 -0
- package/dist/src/workflows/engine/state/interfaces/IStateMachine.js +17 -0
- package/dist/src/workflows/fallback-strategies.js +373 -0
- package/dist/src/workflows/message-queue.js +455 -0
- package/dist/src/workflows/model-router.js +189 -0
- package/dist/src/workflows/orchestrator-examples.js +174 -0
- package/dist/src/workflows/orchestrator-integration.js +200 -0
- package/dist/src/workflows/self-healing.js +524 -0
- package/dist/src/workflows/tool-mapper.js +407 -0
- package/dist/src/workflows/tool-orchestrator.js +796 -0
- package/dist/src/workflows/workflow-engine.js +573 -0
- package/dist/src/workflows/workflow-parser.js +283 -0
- package/dist/src/workflows/workflow-types.js +95 -0
- package/dist/src/workflows.js +568 -0
- package/dist/test-workflow-file-output.js +93 -0
- package/docs/API_KEYS.md +570 -0
- package/docs/CLAUDE_CODE_SETUP.md +181 -0
- package/docs/CLAUDE_DESKTOP_MANUAL.md +127 -0
- package/docs/CONFIGURATION.md +745 -0
- package/docs/FOCUS_MODES.md +240 -0
- package/docs/INSTALLATION_BOTH.md +145 -0
- package/docs/TERMS.md +352 -0
- package/docs/TOOLS_REFERENCE.md +1622 -0
- package/docs/TOOL_PARAMETERS.md +496 -0
- package/docs/TOOL_PROFILES.md +236 -0
- package/docs/WORKFLOWS.md +987 -0
- package/docs/WORKFLOW_OUTPUT.md +198 -0
- package/docs/WORKFLOW_PROGRESS_TRACKING.md +305 -0
- package/docs/workflows/design-brainstorm.md +335 -0
- package/package.json +97 -0
- package/profiles/balanced.json +37 -0
- package/profiles/code_focus.json +37 -0
- package/profiles/debug_intensive.json +34 -0
- package/profiles/full.json +37 -0
- package/profiles/minimal.json +37 -0
- package/profiles/research_power.json +37 -0
- package/profiles/workflow_builder.json +37 -0
- package/smithery.yaml +66 -0
- package/start.sh +8 -0
- package/tools.config.json +81 -0
- package/tsconfig.json +18 -0
- package/workflows/accessibility-code-audit.yaml +92 -0
- package/workflows/code-architecture-review.yaml +202 -0
- package/workflows/code-review.yaml +142 -0
- package/workflows/core/iterative-problem-solver.yaml +283 -0
- package/workflows/creative-brainstorm-yaml.yaml +215 -0
- package/workflows/pingpong.yaml +141 -0
- package/workflows/system/README.md +412 -0
- package/workflows/system/challenger.yaml +175 -0
- package/workflows/system/scout.yaml +164 -0
- package/workflows/system/verifier.yaml +133 -0
- package/workflows/ultra-creative-brainstorm.yaml +318 -0
- package/workflows/ux-research-flow.yaml +92 -0
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Challenger Helper Functions
|
|
3
|
+
*
|
|
4
|
+
* Pure, composable functions for devil's advocate analysis.
|
|
5
|
+
* Used by workflows/system/challenger.yaml
|
|
6
|
+
*
|
|
7
|
+
* Purpose: Expand perspectives, not find faults
|
|
8
|
+
* - Challenge assumptions and basic truths
|
|
9
|
+
* - Find counter-evidence and alternatives
|
|
10
|
+
* - Explore opposite thinking ("what if we're backwards?")
|
|
11
|
+
* - Discover third-way solutions beyond binary choices
|
|
12
|
+
*
|
|
13
|
+
* SOLID Principles:
|
|
14
|
+
* - Single Responsibility: Each function does ONE transformation
|
|
15
|
+
* - Open/Closed: Functions are closed for modification, open for extension
|
|
16
|
+
* - Liskov Substitution: All functions are predictable pure functions
|
|
17
|
+
* - Interface Segregation: Small, focused function signatures
|
|
18
|
+
* - Dependency Inversion: Functions depend on types, not concrete implementations
|
|
19
|
+
*/
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// Tone Detection
|
|
22
|
+
// ============================================================================
|
|
23
|
+
/**
|
|
24
|
+
* Flag uncontested tone - authoritarian language that shuts down dissent
|
|
25
|
+
*
|
|
26
|
+
* Detects phrases like:
|
|
27
|
+
* - "obviously", "clearly", "everyone knows"
|
|
28
|
+
* - "the only way", "undeniably", "without question"
|
|
29
|
+
* - "unanimous", "no disagreement", "settled science"
|
|
30
|
+
*
|
|
31
|
+
* Severity:
|
|
32
|
+
* - high: 3+ phrases (strong groupthink indicators)
|
|
33
|
+
* - medium: 2 phrases
|
|
34
|
+
* - low: 1 phrase
|
|
35
|
+
*/
|
|
36
|
+
export const flagUncontestedTone = (config) => {
|
|
37
|
+
const uncontestedPhrases = [
|
|
38
|
+
'obviously',
|
|
39
|
+
'clearly',
|
|
40
|
+
'everyone knows',
|
|
41
|
+
'everyone agrees',
|
|
42
|
+
'the only way',
|
|
43
|
+
'undeniably',
|
|
44
|
+
'without question',
|
|
45
|
+
'unanimous',
|
|
46
|
+
'no disagreement',
|
|
47
|
+
'settled science',
|
|
48
|
+
'beyond doubt',
|
|
49
|
+
'no alternative',
|
|
50
|
+
'must',
|
|
51
|
+
'always',
|
|
52
|
+
'never'
|
|
53
|
+
];
|
|
54
|
+
const foundPhrases = uncontestedPhrases.filter(phrase => config.text.toLowerCase().includes(phrase));
|
|
55
|
+
const severity = foundPhrases.length >= 3 ? 'high'
|
|
56
|
+
: foundPhrases.length >= 2 ? 'medium'
|
|
57
|
+
: 'low';
|
|
58
|
+
const message = foundPhrases.length === 0
|
|
59
|
+
? 'No uncontested tone detected - healthy room for debate'
|
|
60
|
+
: `Detected ${foundPhrases.length} authoritarian phrase(s) that may shut down dissent`;
|
|
61
|
+
return {
|
|
62
|
+
detected: foundPhrases.length > 0,
|
|
63
|
+
phrases: foundPhrases,
|
|
64
|
+
severity,
|
|
65
|
+
message
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
// ============================================================================
|
|
69
|
+
// Claim Extraction
|
|
70
|
+
// ============================================================================
|
|
71
|
+
/**
|
|
72
|
+
* Extract testable claims from text
|
|
73
|
+
*
|
|
74
|
+
* Claims are statements that can be verified or challenged:
|
|
75
|
+
* - Factual assertions
|
|
76
|
+
* - Predictions
|
|
77
|
+
* - Causal relationships
|
|
78
|
+
* - Generalizations
|
|
79
|
+
*/
|
|
80
|
+
export const extractClaims = (config) => {
|
|
81
|
+
const sentences = config.text.split(/[.!?]+/)
|
|
82
|
+
.map(s => s.trim())
|
|
83
|
+
.filter(s => s.length > 10);
|
|
84
|
+
const claims = [];
|
|
85
|
+
for (const sentence of sentences) {
|
|
86
|
+
const testable = isTestable(sentence);
|
|
87
|
+
const priority = calculateClaimPriority(sentence);
|
|
88
|
+
if (testable && (priority > 0.3 || config.thoroughness === 'deep')) {
|
|
89
|
+
claims.push({
|
|
90
|
+
claim: sentence,
|
|
91
|
+
context: extractContext(sentence, config.text),
|
|
92
|
+
testable,
|
|
93
|
+
priority
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return claims;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Prioritize claims for fact-checking
|
|
101
|
+
*
|
|
102
|
+
* Returns top N claims by priority score
|
|
103
|
+
*/
|
|
104
|
+
export const prioritizeClaims = (config) => {
|
|
105
|
+
return [...config.claims]
|
|
106
|
+
.sort((a, b) => b.priority - a.priority)
|
|
107
|
+
.slice(0, config.max_claims);
|
|
108
|
+
};
|
|
109
|
+
// ============================================================================
|
|
110
|
+
// Opposite Thinking
|
|
111
|
+
// ============================================================================
|
|
112
|
+
/**
|
|
113
|
+
* Explore "what if we're backwards?" perspective
|
|
114
|
+
*
|
|
115
|
+
* For each claim, explore the opposite view and assess plausibility
|
|
116
|
+
*/
|
|
117
|
+
export const exploreOppositeThinking = (config) => {
|
|
118
|
+
return config.claims.map(claim => {
|
|
119
|
+
const oppositeView = generateOppositeView(claim.claim);
|
|
120
|
+
const evidence = extractRelevantEvidence(claim.claim, config.counter_evidence || '');
|
|
121
|
+
const plausibility = assessOppositeViewPlausibility(claim.claim, oppositeView, config.fact_check || '', config.counter_evidence || '');
|
|
122
|
+
return {
|
|
123
|
+
original_claim: claim.claim,
|
|
124
|
+
opposite_view: oppositeView,
|
|
125
|
+
plausibility,
|
|
126
|
+
evidence,
|
|
127
|
+
source: 'research'
|
|
128
|
+
};
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Find "third way" alternatives beyond binary thinking
|
|
133
|
+
*
|
|
134
|
+
* When everyone sees only A vs B, find option C, D, E
|
|
135
|
+
*/
|
|
136
|
+
export const findThirdWay = (config) => {
|
|
137
|
+
const binaryClaims = config.claims.filter(claim => isBinaryChoice(claim.claim));
|
|
138
|
+
return binaryClaims.map(claim => {
|
|
139
|
+
const alternatives = generateThirdWayAlternatives(claim.claim, config.fact_check || '', config.counter_evidence || '');
|
|
140
|
+
const confidence = calculateAlternativeConfidence(alternatives, config.fact_check || '', config.counter_evidence || '');
|
|
141
|
+
return {
|
|
142
|
+
original_claim: claim.claim,
|
|
143
|
+
alternatives,
|
|
144
|
+
confidence,
|
|
145
|
+
source: 'research'
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
};
|
|
149
|
+
// ============================================================================
|
|
150
|
+
// Synthesis
|
|
151
|
+
// ============================================================================
|
|
152
|
+
/**
|
|
153
|
+
* Synthesize all challenges into coherent report
|
|
154
|
+
*/
|
|
155
|
+
export const synthesizeChallengerReport = (config) => {
|
|
156
|
+
let synthesis = `## 🎯 Devil's Advocate Analysis\n\n`;
|
|
157
|
+
// Tone Analysis Section
|
|
158
|
+
synthesis += `### 📢 Tone Analysis\n\n`;
|
|
159
|
+
synthesis += `**Status:** ${config.tone_analysis.detected ? '⚠️ Uncontested Tone Detected' : '✅ Healthy Debate Room'}\n`;
|
|
160
|
+
synthesis += `**Severity:** ${config.tone_analysis.severity.toUpperCase()}\n`;
|
|
161
|
+
synthesis += `**Message:** ${config.tone_analysis.message}\n\n`;
|
|
162
|
+
if (config.tone_analysis.phrases.length > 0) {
|
|
163
|
+
synthesis += `**Authoritarian phrases found:**\n`;
|
|
164
|
+
config.tone_analysis.phrases.forEach(phrase => {
|
|
165
|
+
synthesis += `- "${phrase}"\n`;
|
|
166
|
+
});
|
|
167
|
+
synthesis += `\n`;
|
|
168
|
+
}
|
|
169
|
+
// Claims Analysis
|
|
170
|
+
synthesis += `### 🔍 Claims Analyzed: ${config.claims.length}\n\n`;
|
|
171
|
+
if (config.claims.length > 0) {
|
|
172
|
+
synthesis += buildClaimsTable(config.claims.slice(0, 5));
|
|
173
|
+
synthesis += `\n`;
|
|
174
|
+
}
|
|
175
|
+
// Fact-Check Results
|
|
176
|
+
if (config.fact_check) {
|
|
177
|
+
synthesis += `### ✓ Fact-Check Results\n\n`;
|
|
178
|
+
synthesis += formatFactCheckResults(config.fact_check);
|
|
179
|
+
synthesis += `\n`;
|
|
180
|
+
}
|
|
181
|
+
// Counter-Evidence
|
|
182
|
+
if (config.counter_evidence) {
|
|
183
|
+
synthesis += `### ⚡ Counter-Evidence\n\n`;
|
|
184
|
+
synthesis += formatCounterEvidence(config.counter_evidence);
|
|
185
|
+
synthesis += `\n`;
|
|
186
|
+
}
|
|
187
|
+
// Opposite Views
|
|
188
|
+
if (config.opposite_views && config.opposite_views.length > 0) {
|
|
189
|
+
synthesis += `### 🔄 Opposite Thinking ("What if we're backwards?")\n\n`;
|
|
190
|
+
config.opposite_views.forEach(view => {
|
|
191
|
+
synthesis += `**Original:** ${view.original_claim}\n`;
|
|
192
|
+
synthesis += `**Opposite:** ${view.opposite_view}\n`;
|
|
193
|
+
synthesis += `**Plausibility:** ${(view.plausibility * 100).toFixed(0)}%\n\n`;
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
// Third-Way Alternatives
|
|
197
|
+
if (config.third_way && config.third_way.length > 0) {
|
|
198
|
+
synthesis += `### 🌟 Third-Way Alternatives (Beyond Binary Thinking)\n\n`;
|
|
199
|
+
config.third_way.forEach(alt => {
|
|
200
|
+
synthesis += `**Original:** ${alt.original_claim}\n`;
|
|
201
|
+
synthesis += `**Alternatives:**\n`;
|
|
202
|
+
alt.alternatives.forEach(a => synthesis += `- ${a}\n`);
|
|
203
|
+
synthesis += `**Confidence:** ${(alt.confidence * 100).toFixed(0)}%\n\n`;
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
// Summary
|
|
207
|
+
synthesis += `### 📋 Summary\n\n`;
|
|
208
|
+
synthesis += `\`\`\`\n`;
|
|
209
|
+
synthesis += `Thoroughness: ${config.thoroughness}\n`;
|
|
210
|
+
synthesis += `Claims Analyzed: ${config.claims.length}\n`;
|
|
211
|
+
synthesis += `Tone Detected: ${config.tone_analysis.detected ? 'YES ⚠️' : 'NO ✅'}\n`;
|
|
212
|
+
synthesis += `Fact-Checked: ${config.fact_check ? 'YES ✓' : 'NO'}\n`;
|
|
213
|
+
synthesis += `Counter-Evidence: ${config.counter_evidence ? 'YES ✓' : 'NO'}\n`;
|
|
214
|
+
synthesis += `Opposite Views: ${config.opposite_views?.length || 0}\n`;
|
|
215
|
+
synthesis += `Third-Way Options: ${config.third_way?.length || 0}\n`;
|
|
216
|
+
synthesis += `\`\`\`\n`;
|
|
217
|
+
return synthesis;
|
|
218
|
+
};
|
|
219
|
+
/**
|
|
220
|
+
* Calculate overall challenge score (strength of counter-arguments)
|
|
221
|
+
*
|
|
222
|
+
* Score based on:
|
|
223
|
+
* - Fact-check contradictions (40%)
|
|
224
|
+
* - Counter-evidence strength (30%)
|
|
225
|
+
* - Opposite view plausibility (15%)
|
|
226
|
+
* - Third-way alternatives (15%)
|
|
227
|
+
*/
|
|
228
|
+
export const calculateChallengeScore = (config) => {
|
|
229
|
+
let score = 0;
|
|
230
|
+
// Fact-check contradictions (40%)
|
|
231
|
+
if (config.fact_check) {
|
|
232
|
+
const contradictions = (config.fact_check.match(/refuted|false|incorrect/gi) || []).length;
|
|
233
|
+
score += Math.min(contradictions * 0.1, 0.4);
|
|
234
|
+
}
|
|
235
|
+
// Counter-evidence strength (30%)
|
|
236
|
+
if (config.counter_evidence) {
|
|
237
|
+
const counterArgs = (config.counter_evidence.match(/however|but|alternative|dissent/gi) || []).length;
|
|
238
|
+
score += Math.min(counterArgs * 0.05, 0.3);
|
|
239
|
+
}
|
|
240
|
+
// Opposite view plausibility (15%)
|
|
241
|
+
if (config.opposite_views && config.opposite_views.length > 0) {
|
|
242
|
+
const avgPlausibility = config.opposite_views.reduce((sum, v) => sum + v.plausibility, 0) / config.opposite_views.length;
|
|
243
|
+
score += avgPlausibility * 0.15;
|
|
244
|
+
}
|
|
245
|
+
// Third-way alternatives (15%)
|
|
246
|
+
if (config.third_way && config.third_way.length > 0) {
|
|
247
|
+
const avgConfidence = config.third_way.reduce((sum, t) => sum + t.confidence, 0) / config.third_way.length;
|
|
248
|
+
score += avgConfidence * 0.15;
|
|
249
|
+
}
|
|
250
|
+
return Math.min(score, 1.0);
|
|
251
|
+
};
|
|
252
|
+
/**
|
|
253
|
+
* Format final challenger result
|
|
254
|
+
*/
|
|
255
|
+
export const formatChallengerResult = (config) => {
|
|
256
|
+
return {
|
|
257
|
+
synthesis: config.synthesis,
|
|
258
|
+
tone_analysis: config.tone_analysis,
|
|
259
|
+
claims_analyzed: config.claims_analyzed,
|
|
260
|
+
challenge_score: config.challenge_score,
|
|
261
|
+
fact_check_results: config.fact_check_results ? parseFactCheckResults(config.fact_check_results) : undefined,
|
|
262
|
+
counter_evidence_results: config.counter_evidence_results ? parseCounterEvidenceResults(config.counter_evidence_results) : undefined,
|
|
263
|
+
opposite_views: config.opposite_views || undefined,
|
|
264
|
+
third_way_alternatives: config.third_way_alternatives || undefined
|
|
265
|
+
};
|
|
266
|
+
};
|
|
267
|
+
// ============================================================================
|
|
268
|
+
// Internal Utilities
|
|
269
|
+
// ============================================================================
|
|
270
|
+
/**
|
|
271
|
+
* Check if sentence is testable (can be verified or challenged)
|
|
272
|
+
*/
|
|
273
|
+
const isTestable = (sentence) => {
|
|
274
|
+
const testableIndicators = [
|
|
275
|
+
/\b(is|are|was|were|will|would|can|could|should|must)\b/i,
|
|
276
|
+
/\b(all|every|always|never|most|many|some|few)\b/i,
|
|
277
|
+
/\b(cause|result|lead|increase|decrease|improve|reduce)\b/i,
|
|
278
|
+
/\b(better|worse|faster|slower|more|less)\b/i
|
|
279
|
+
];
|
|
280
|
+
return testableIndicators.some(pattern => pattern.test(sentence));
|
|
281
|
+
};
|
|
282
|
+
/**
|
|
283
|
+
* Calculate claim priority score (0-1)
|
|
284
|
+
*
|
|
285
|
+
* Higher priority for:
|
|
286
|
+
* - Causal claims ("X causes Y")
|
|
287
|
+
* - Generalizations ("all", "never", "always")
|
|
288
|
+
* - Comparative claims ("better than", "more effective")
|
|
289
|
+
* - Predictions ("will", "going to")
|
|
290
|
+
*/
|
|
291
|
+
const calculateClaimPriority = (sentence) => {
|
|
292
|
+
let priority = 0;
|
|
293
|
+
// Causal language (+0.4)
|
|
294
|
+
if (/\b(cause|result|lead|due to|because of)\b/i.test(sentence)) {
|
|
295
|
+
priority += 0.4;
|
|
296
|
+
}
|
|
297
|
+
// Generalizations (+0.3)
|
|
298
|
+
if (/\b(all|every|always|never|none)\b/i.test(sentence)) {
|
|
299
|
+
priority += 0.3;
|
|
300
|
+
}
|
|
301
|
+
// Comparatives (+0.2)
|
|
302
|
+
if (/\b(better|worse|more|less|faster|slower|superior|inferior)\b/i.test(sentence)) {
|
|
303
|
+
priority += 0.2;
|
|
304
|
+
}
|
|
305
|
+
// Predictions (+0.2)
|
|
306
|
+
if (/\b(will|going to|predict|forecast|expect)\b/i.test(sentence)) {
|
|
307
|
+
priority += 0.2;
|
|
308
|
+
}
|
|
309
|
+
return Math.min(priority, 1.0);
|
|
310
|
+
};
|
|
311
|
+
/**
|
|
312
|
+
* Extract context around a claim
|
|
313
|
+
*/
|
|
314
|
+
const extractContext = (claim, fullText) => {
|
|
315
|
+
const index = fullText.indexOf(claim);
|
|
316
|
+
if (index === -1)
|
|
317
|
+
return claim;
|
|
318
|
+
const start = Math.max(0, index - 100);
|
|
319
|
+
const end = Math.min(fullText.length, index + claim.length + 100);
|
|
320
|
+
return fullText.substring(start, end);
|
|
321
|
+
};
|
|
322
|
+
/**
|
|
323
|
+
* Generate opposite view for a claim
|
|
324
|
+
*/
|
|
325
|
+
const generateOppositeView = (claim) => {
|
|
326
|
+
// Simple negation (in real implementation, this would be more sophisticated)
|
|
327
|
+
if (claim.toLowerCase().includes('should')) {
|
|
328
|
+
return claim.replace(/should/i, 'should not');
|
|
329
|
+
}
|
|
330
|
+
if (claim.toLowerCase().includes('must')) {
|
|
331
|
+
return claim.replace(/must/i, 'must not');
|
|
332
|
+
}
|
|
333
|
+
if (claim.toLowerCase().includes('always')) {
|
|
334
|
+
return claim.replace(/always/i, 'never');
|
|
335
|
+
}
|
|
336
|
+
if (claim.toLowerCase().includes('never')) {
|
|
337
|
+
return claim.replace(/never/i, 'always');
|
|
338
|
+
}
|
|
339
|
+
return `The opposite view: ${claim} may not be true`;
|
|
340
|
+
};
|
|
341
|
+
/**
|
|
342
|
+
* Extract relevant evidence from counter-evidence text
|
|
343
|
+
*/
|
|
344
|
+
const extractRelevantEvidence = (claim, counterEvidence) => {
|
|
345
|
+
if (!counterEvidence)
|
|
346
|
+
return [];
|
|
347
|
+
const keywords = claim.toLowerCase().split(/\s+/).filter(w => w.length > 3);
|
|
348
|
+
const sentences = counterEvidence.split(/[.!?]+/);
|
|
349
|
+
const relevant = sentences.filter(sentence => keywords.some(keyword => sentence.toLowerCase().includes(keyword)));
|
|
350
|
+
return relevant.slice(0, 3);
|
|
351
|
+
};
|
|
352
|
+
/**
|
|
353
|
+
* Assess plausibility of opposite view
|
|
354
|
+
*/
|
|
355
|
+
const assessOppositeViewPlausibility = (claim, oppositeView, factCheck, counterEvidence) => {
|
|
356
|
+
let plausibility = 0.3; // Base plausibility
|
|
357
|
+
// Check if counter-evidence supports opposite view
|
|
358
|
+
const keywords = oppositeView.toLowerCase().split(/\s+/).filter(w => w.length > 3);
|
|
359
|
+
const matches = keywords.filter(keyword => counterEvidence.toLowerCase().includes(keyword)).length;
|
|
360
|
+
plausibility += Math.min(matches * 0.1, 0.4);
|
|
361
|
+
// Check fact-check contradictions
|
|
362
|
+
if (factCheck.toLowerCase().includes('refuted') || factCheck.toLowerCase().includes('false')) {
|
|
363
|
+
plausibility += 0.3;
|
|
364
|
+
}
|
|
365
|
+
return Math.min(plausibility, 1.0);
|
|
366
|
+
};
|
|
367
|
+
/**
|
|
368
|
+
* Check if claim represents binary choice
|
|
369
|
+
*/
|
|
370
|
+
const isBinaryChoice = (claim) => {
|
|
371
|
+
return /\b(or|versus|vs|either|choice|alternative)\b/i.test(claim);
|
|
372
|
+
};
|
|
373
|
+
/**
|
|
374
|
+
* Generate third-way alternatives
|
|
375
|
+
*/
|
|
376
|
+
const generateThirdWayAlternatives = (claim, factCheck, counterEvidence) => {
|
|
377
|
+
const alternatives = [];
|
|
378
|
+
// Extract alternative approaches from evidence
|
|
379
|
+
const altPattern = /alternative|another way|instead|different approach/gi;
|
|
380
|
+
const sentences = (factCheck + ' ' + counterEvidence).split(/[.!?]+/);
|
|
381
|
+
sentences.forEach(sentence => {
|
|
382
|
+
if (altPattern.test(sentence) && sentence.length > 20) {
|
|
383
|
+
alternatives.push(sentence.trim());
|
|
384
|
+
}
|
|
385
|
+
});
|
|
386
|
+
// Add synthetic alternatives if needed
|
|
387
|
+
if (alternatives.length === 0) {
|
|
388
|
+
alternatives.push(`Hybrid approach combining elements of both perspectives`);
|
|
389
|
+
alternatives.push(`Context-dependent solution varying by situation`);
|
|
390
|
+
alternatives.push(`Gradual transition rather than binary switch`);
|
|
391
|
+
}
|
|
392
|
+
return alternatives.slice(0, 5);
|
|
393
|
+
};
|
|
394
|
+
/**
|
|
395
|
+
* Calculate confidence in alternatives
|
|
396
|
+
*/
|
|
397
|
+
const calculateAlternativeConfidence = (alternatives, factCheck, counterEvidence) => {
|
|
398
|
+
// Higher confidence if alternatives are derived from evidence
|
|
399
|
+
const evidenceBased = alternatives.filter(alt => factCheck.includes(alt.substring(0, 20)) || counterEvidence.includes(alt.substring(0, 20))).length;
|
|
400
|
+
return Math.min(0.5 + (evidenceBased * 0.15), 0.95);
|
|
401
|
+
};
|
|
402
|
+
/**
|
|
403
|
+
* Build claims table
|
|
404
|
+
*/
|
|
405
|
+
const buildClaimsTable = (claims) => {
|
|
406
|
+
let table = '| Priority | Claim | Testable |\n';
|
|
407
|
+
table += '|---------:|:------|:--------:|\n';
|
|
408
|
+
claims.forEach(claim => {
|
|
409
|
+
const priority = (claim.priority * 100).toFixed(0) + '%';
|
|
410
|
+
const claimText = claim.claim.length > 80 ? claim.claim.substring(0, 77) + '...' : claim.claim;
|
|
411
|
+
const testable = claim.testable ? '✓' : '✗';
|
|
412
|
+
table += `| ${priority} | ${claimText} | ${testable} |\n`;
|
|
413
|
+
});
|
|
414
|
+
return table;
|
|
415
|
+
};
|
|
416
|
+
/**
|
|
417
|
+
* Format fact-check results
|
|
418
|
+
*/
|
|
419
|
+
const formatFactCheckResults = (factCheck) => {
|
|
420
|
+
return factCheck.substring(0, 500) + (factCheck.length > 500 ? '...' : '');
|
|
421
|
+
};
|
|
422
|
+
/**
|
|
423
|
+
* Format counter-evidence
|
|
424
|
+
*/
|
|
425
|
+
const formatCounterEvidence = (counterEvidence) => {
|
|
426
|
+
return counterEvidence.substring(0, 500) + (counterEvidence.length > 500 ? '...' : '');
|
|
427
|
+
};
|
|
428
|
+
/**
|
|
429
|
+
* Parse fact-check results into structured format
|
|
430
|
+
*/
|
|
431
|
+
const parseFactCheckResults = (factCheck) => {
|
|
432
|
+
// Simplified parsing (real implementation would be more sophisticated)
|
|
433
|
+
return [{
|
|
434
|
+
claim: 'Sample claim',
|
|
435
|
+
status: 'uncertain',
|
|
436
|
+
supporting_evidence: [],
|
|
437
|
+
contradicting_evidence: [],
|
|
438
|
+
sources: [],
|
|
439
|
+
reliability: 0.5
|
|
440
|
+
}];
|
|
441
|
+
};
|
|
442
|
+
/**
|
|
443
|
+
* Parse counter-evidence into structured format
|
|
444
|
+
*/
|
|
445
|
+
const parseCounterEvidenceResults = (counterEvidence) => {
|
|
446
|
+
// Simplified parsing
|
|
447
|
+
return [{
|
|
448
|
+
claim: 'Sample claim',
|
|
449
|
+
counter_arguments: [],
|
|
450
|
+
dissenting_experts: [],
|
|
451
|
+
alternative_interpretations: [],
|
|
452
|
+
edge_cases: []
|
|
453
|
+
}];
|
|
454
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Helper Functions for System Workflows
|
|
3
|
+
*
|
|
4
|
+
* This module exports pure, composable helper functions used by
|
|
5
|
+
* system workflows (scout, verifier, challenger).
|
|
6
|
+
*
|
|
7
|
+
* SOLID Principles Applied:
|
|
8
|
+
* - Single Responsibility: Each helper module focuses on one mode
|
|
9
|
+
* - Open/Closed: Helpers are closed for modification, open for extension
|
|
10
|
+
* - Dependency Inversion: Workflows depend on these abstractions
|
|
11
|
+
*/
|
|
12
|
+
// Scout helpers
|
|
13
|
+
export * from './scout-helpers.js';
|
|
14
|
+
// Verifier helpers
|
|
15
|
+
export * from './verifier-helpers.js';
|
|
16
|
+
// Challenger helpers
|
|
17
|
+
export * from './challenger-helpers.js';
|