wogiflow 1.0.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.
- package/.workflow/agents/reviewer.md +81 -0
- package/.workflow/agents/security.md +94 -0
- package/.workflow/agents/story-writer.md +58 -0
- package/.workflow/bridges/base-bridge.js +395 -0
- package/.workflow/bridges/claude-bridge.js +434 -0
- package/.workflow/bridges/index.js +130 -0
- package/.workflow/lib/assumption-detector.js +481 -0
- package/.workflow/lib/config-substitution.js +371 -0
- package/.workflow/lib/failure-categories.js +478 -0
- package/.workflow/state/app-map.md.template +15 -0
- package/.workflow/state/architecture.md.template +24 -0
- package/.workflow/state/component-index.json.template +5 -0
- package/.workflow/state/decisions.md.template +15 -0
- package/.workflow/state/feedback-patterns.md.template +9 -0
- package/.workflow/state/knowledge-sync.json.template +6 -0
- package/.workflow/state/progress.md.template +14 -0
- package/.workflow/state/ready.json.template +7 -0
- package/.workflow/state/request-log.md.template +14 -0
- package/.workflow/state/session-state.json.template +11 -0
- package/.workflow/state/stack.md.template +33 -0
- package/.workflow/state/testing.md.template +36 -0
- package/.workflow/templates/claude-md.hbs +257 -0
- package/.workflow/templates/correction-report.md +67 -0
- package/.workflow/templates/gemini-md.hbs +52 -0
- package/README.md +1802 -0
- package/bin/flow +205 -0
- package/lib/index.js +33 -0
- package/lib/installer.js +467 -0
- package/lib/release-channel.js +269 -0
- package/lib/skill-registry.js +526 -0
- package/lib/upgrader.js +401 -0
- package/lib/utils.js +305 -0
- package/package.json +64 -0
- package/scripts/flow +985 -0
- package/scripts/flow-adaptive-learning.js +1259 -0
- package/scripts/flow-aggregate.js +488 -0
- package/scripts/flow-archive +133 -0
- package/scripts/flow-auto-context.js +1015 -0
- package/scripts/flow-auto-learn.js +615 -0
- package/scripts/flow-bridge.js +223 -0
- package/scripts/flow-browser-suggest.js +316 -0
- package/scripts/flow-bug.js +247 -0
- package/scripts/flow-cascade.js +711 -0
- package/scripts/flow-changelog +85 -0
- package/scripts/flow-checkpoint.js +483 -0
- package/scripts/flow-cli.js +403 -0
- package/scripts/flow-code-intelligence.js +760 -0
- package/scripts/flow-complexity.js +502 -0
- package/scripts/flow-config-set.js +152 -0
- package/scripts/flow-constants.js +157 -0
- package/scripts/flow-context +152 -0
- package/scripts/flow-context-init.js +482 -0
- package/scripts/flow-context-monitor.js +384 -0
- package/scripts/flow-context-scoring.js +886 -0
- package/scripts/flow-correct.js +458 -0
- package/scripts/flow-damage-control.js +985 -0
- package/scripts/flow-deps +101 -0
- package/scripts/flow-diff.js +700 -0
- package/scripts/flow-done +151 -0
- package/scripts/flow-done.js +489 -0
- package/scripts/flow-durable-session.js +1541 -0
- package/scripts/flow-entropy-monitor.js +345 -0
- package/scripts/flow-export-profile +349 -0
- package/scripts/flow-export-scanner.js +1046 -0
- package/scripts/flow-figma-confirm.js +400 -0
- package/scripts/flow-figma-extract.js +496 -0
- package/scripts/flow-figma-generate.js +683 -0
- package/scripts/flow-figma-index.js +909 -0
- package/scripts/flow-figma-match.js +617 -0
- package/scripts/flow-figma-mcp-server.js +518 -0
- package/scripts/flow-figma-pipeline.js +414 -0
- package/scripts/flow-file-ops.js +301 -0
- package/scripts/flow-gate-confidence.js +825 -0
- package/scripts/flow-guided-edit.js +659 -0
- package/scripts/flow-health +185 -0
- package/scripts/flow-health.js +413 -0
- package/scripts/flow-hooks.js +556 -0
- package/scripts/flow-http-client.js +249 -0
- package/scripts/flow-hybrid-detect.js +167 -0
- package/scripts/flow-hybrid-interactive.js +591 -0
- package/scripts/flow-hybrid-test.js +152 -0
- package/scripts/flow-import-profile +439 -0
- package/scripts/flow-init +253 -0
- package/scripts/flow-instruction-richness.js +827 -0
- package/scripts/flow-jira-integration.js +579 -0
- package/scripts/flow-knowledge-router.js +522 -0
- package/scripts/flow-knowledge-sync.js +589 -0
- package/scripts/flow-linear-integration.js +631 -0
- package/scripts/flow-links.js +774 -0
- package/scripts/flow-log-manager.js +559 -0
- package/scripts/flow-loop-enforcer.js +1246 -0
- package/scripts/flow-loop-retry-learning.js +630 -0
- package/scripts/flow-lsp.js +923 -0
- package/scripts/flow-map-index +348 -0
- package/scripts/flow-map-sync +201 -0
- package/scripts/flow-memory-blocks.js +668 -0
- package/scripts/flow-memory-compactor.js +350 -0
- package/scripts/flow-memory-db.js +1110 -0
- package/scripts/flow-memory-sync.js +484 -0
- package/scripts/flow-metrics.js +353 -0
- package/scripts/flow-migrate-ids.js +370 -0
- package/scripts/flow-model-adapter.js +802 -0
- package/scripts/flow-model-router.js +884 -0
- package/scripts/flow-models.js +1231 -0
- package/scripts/flow-morning.js +517 -0
- package/scripts/flow-multi-approach.js +660 -0
- package/scripts/flow-new-feature +86 -0
- package/scripts/flow-onboard +1042 -0
- package/scripts/flow-orchestrate-llm.js +459 -0
- package/scripts/flow-orchestrate.js +3592 -0
- package/scripts/flow-output.js +123 -0
- package/scripts/flow-parallel-detector.js +399 -0
- package/scripts/flow-parallel-dispatch.js +987 -0
- package/scripts/flow-parallel.js +428 -0
- package/scripts/flow-pattern-enforcer.js +600 -0
- package/scripts/flow-prd-manager.js +282 -0
- package/scripts/flow-progress.js +323 -0
- package/scripts/flow-project-analyzer.js +975 -0
- package/scripts/flow-prompt-composer.js +487 -0
- package/scripts/flow-providers.js +1381 -0
- package/scripts/flow-queue.js +308 -0
- package/scripts/flow-ready +82 -0
- package/scripts/flow-ready.js +189 -0
- package/scripts/flow-regression.js +396 -0
- package/scripts/flow-response-parser.js +450 -0
- package/scripts/flow-resume.js +284 -0
- package/scripts/flow-rules-sync.js +439 -0
- package/scripts/flow-run-trace.js +718 -0
- package/scripts/flow-safety.js +587 -0
- package/scripts/flow-search +104 -0
- package/scripts/flow-security.js +481 -0
- package/scripts/flow-session-end +106 -0
- package/scripts/flow-session-end.js +437 -0
- package/scripts/flow-session-state.js +671 -0
- package/scripts/flow-setup-hooks +216 -0
- package/scripts/flow-setup-hooks.js +377 -0
- package/scripts/flow-skill-create.js +329 -0
- package/scripts/flow-skill-creator.js +572 -0
- package/scripts/flow-skill-generator.js +1046 -0
- package/scripts/flow-skill-learn.js +880 -0
- package/scripts/flow-skill-matcher.js +578 -0
- package/scripts/flow-spec-generator.js +820 -0
- package/scripts/flow-stack-wizard.js +895 -0
- package/scripts/flow-standup +162 -0
- package/scripts/flow-start +74 -0
- package/scripts/flow-start.js +235 -0
- package/scripts/flow-status +110 -0
- package/scripts/flow-status.js +301 -0
- package/scripts/flow-step-browser.js +83 -0
- package/scripts/flow-step-changelog.js +217 -0
- package/scripts/flow-step-comments.js +306 -0
- package/scripts/flow-step-complexity.js +234 -0
- package/scripts/flow-step-coverage.js +218 -0
- package/scripts/flow-step-knowledge.js +193 -0
- package/scripts/flow-step-pr-tests.js +364 -0
- package/scripts/flow-step-regression.js +89 -0
- package/scripts/flow-step-review.js +516 -0
- package/scripts/flow-step-security.js +162 -0
- package/scripts/flow-step-silent-failures.js +290 -0
- package/scripts/flow-step-simplifier.js +346 -0
- package/scripts/flow-story +105 -0
- package/scripts/flow-story.js +500 -0
- package/scripts/flow-suspend.js +252 -0
- package/scripts/flow-sync-daemon.js +654 -0
- package/scripts/flow-task-analyzer.js +606 -0
- package/scripts/flow-team-dashboard.js +748 -0
- package/scripts/flow-team-sync.js +752 -0
- package/scripts/flow-team.js +977 -0
- package/scripts/flow-tech-options.js +528 -0
- package/scripts/flow-templates.js +812 -0
- package/scripts/flow-tiered-learning.js +728 -0
- package/scripts/flow-trace +204 -0
- package/scripts/flow-transcript-chunking.js +1106 -0
- package/scripts/flow-transcript-digest.js +7918 -0
- package/scripts/flow-transcript-language.js +465 -0
- package/scripts/flow-transcript-parsing.js +1085 -0
- package/scripts/flow-transcript-stories.js +2194 -0
- package/scripts/flow-update-map +224 -0
- package/scripts/flow-utils.js +2242 -0
- package/scripts/flow-verification.js +644 -0
- package/scripts/flow-verify.js +1177 -0
- package/scripts/flow-voice-input.js +638 -0
- package/scripts/flow-watch +168 -0
- package/scripts/flow-workflow-steps.js +521 -0
- package/scripts/flow-workflow.js +1029 -0
- package/scripts/flow-worktree.js +489 -0
- package/scripts/hooks/adapters/base-adapter.js +102 -0
- package/scripts/hooks/adapters/claude-code.js +359 -0
- package/scripts/hooks/adapters/index.js +79 -0
- package/scripts/hooks/core/component-check.js +341 -0
- package/scripts/hooks/core/index.js +35 -0
- package/scripts/hooks/core/loop-check.js +241 -0
- package/scripts/hooks/core/session-context.js +294 -0
- package/scripts/hooks/core/task-gate.js +177 -0
- package/scripts/hooks/core/validation.js +230 -0
- package/scripts/hooks/entry/claude-code/post-tool-use.js +65 -0
- package/scripts/hooks/entry/claude-code/pre-tool-use.js +89 -0
- package/scripts/hooks/entry/claude-code/session-end.js +87 -0
- package/scripts/hooks/entry/claude-code/session-start.js +46 -0
- package/scripts/hooks/entry/claude-code/stop.js +43 -0
- package/scripts/postinstall.js +139 -0
- package/templates/browser-test-flow.json +56 -0
- package/templates/bug-report.md +43 -0
- package/templates/component-detail.md +42 -0
- package/templates/component.stories.tsx +49 -0
- package/templates/context/constraints.md +83 -0
- package/templates/context/conventions.md +177 -0
- package/templates/context/stack.md +60 -0
- package/templates/correction-report.md +90 -0
- package/templates/feature-proposal.md +35 -0
- package/templates/hybrid/_base.md +254 -0
- package/templates/hybrid/_patterns.md +45 -0
- package/templates/hybrid/create-component.md +127 -0
- package/templates/hybrid/create-file.md +56 -0
- package/templates/hybrid/create-hook.md +145 -0
- package/templates/hybrid/create-service.md +70 -0
- package/templates/hybrid/fix-bug.md +33 -0
- package/templates/hybrid/modify-file.md +55 -0
- package/templates/story.md +68 -0
- package/templates/task.json +56 -0
- package/templates/trace.md +69 -0
|
@@ -0,0 +1,825 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* flow-gate-confidence.js
|
|
5
|
+
*
|
|
6
|
+
* Phase 4.3: Quality Gate Confidence System
|
|
7
|
+
*
|
|
8
|
+
* Analyzes AI responses to detect confidence levels.
|
|
9
|
+
* Don't auto-apply low-confidence changes.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* node flow-gate-confidence.js analyze "<response text>"
|
|
13
|
+
* node flow-gate-confidence.js check --file <file>
|
|
14
|
+
* node flow-gate-confidence.js stats
|
|
15
|
+
*
|
|
16
|
+
* @module flow-gate-confidence
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
const fs = require('fs');
|
|
20
|
+
const path = require('path');
|
|
21
|
+
|
|
22
|
+
// ============================================================
|
|
23
|
+
// Imports
|
|
24
|
+
// ============================================================
|
|
25
|
+
|
|
26
|
+
const PROJECT_ROOT = path.resolve(__dirname, '..');
|
|
27
|
+
|
|
28
|
+
const {
|
|
29
|
+
getConfig,
|
|
30
|
+
parseFlags,
|
|
31
|
+
info,
|
|
32
|
+
success,
|
|
33
|
+
warn,
|
|
34
|
+
error,
|
|
35
|
+
color,
|
|
36
|
+
outputJson,
|
|
37
|
+
printHeader,
|
|
38
|
+
printSection,
|
|
39
|
+
safeJsonParse
|
|
40
|
+
} = require('./flow-utils');
|
|
41
|
+
|
|
42
|
+
// ============================================================
|
|
43
|
+
// Constants
|
|
44
|
+
// ============================================================
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* High confidence markers - indicate the model is sure.
|
|
48
|
+
*/
|
|
49
|
+
const HIGH_CONFIDENCE_MARKERS = [
|
|
50
|
+
// Direct confidence statements
|
|
51
|
+
"I'm confident",
|
|
52
|
+
"I am confident",
|
|
53
|
+
"This will work",
|
|
54
|
+
"This is correct",
|
|
55
|
+
"This is the right",
|
|
56
|
+
"Straightforward",
|
|
57
|
+
"Simple fix",
|
|
58
|
+
"Standard approach",
|
|
59
|
+
"Best practice",
|
|
60
|
+
"Recommended way",
|
|
61
|
+
|
|
62
|
+
// Certainty indicators
|
|
63
|
+
"Definitely",
|
|
64
|
+
"Certainly",
|
|
65
|
+
"Absolutely",
|
|
66
|
+
"Without a doubt",
|
|
67
|
+
"Clearly",
|
|
68
|
+
"Obviously",
|
|
69
|
+
|
|
70
|
+
// Knowledge indicators
|
|
71
|
+
"I know that",
|
|
72
|
+
"This is because",
|
|
73
|
+
"The reason is",
|
|
74
|
+
"According to the docs",
|
|
75
|
+
"Per the documentation",
|
|
76
|
+
|
|
77
|
+
// Action confidence
|
|
78
|
+
"Here's the solution",
|
|
79
|
+
"The fix is",
|
|
80
|
+
"You should",
|
|
81
|
+
"You need to",
|
|
82
|
+
"Make sure to"
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Low confidence markers - indicate uncertainty.
|
|
87
|
+
*/
|
|
88
|
+
const LOW_CONFIDENCE_MARKERS = [
|
|
89
|
+
// Uncertainty hedges
|
|
90
|
+
"I think",
|
|
91
|
+
"I believe",
|
|
92
|
+
"I assume",
|
|
93
|
+
"I suppose",
|
|
94
|
+
"I guess",
|
|
95
|
+
"I'm not sure",
|
|
96
|
+
"I'm not certain",
|
|
97
|
+
"I'm not entirely sure",
|
|
98
|
+
"I'm unsure",
|
|
99
|
+
|
|
100
|
+
// Possibility hedges
|
|
101
|
+
"Might work",
|
|
102
|
+
"May work",
|
|
103
|
+
"Could work",
|
|
104
|
+
"Should work",
|
|
105
|
+
"Possibly",
|
|
106
|
+
"Perhaps",
|
|
107
|
+
"Maybe",
|
|
108
|
+
"Probably",
|
|
109
|
+
|
|
110
|
+
// Uncertainty indicators
|
|
111
|
+
"Not entirely sure",
|
|
112
|
+
"Not completely certain",
|
|
113
|
+
"Hard to say",
|
|
114
|
+
"Difficult to tell",
|
|
115
|
+
"Unclear",
|
|
116
|
+
"Uncertain",
|
|
117
|
+
|
|
118
|
+
// Conditional language
|
|
119
|
+
"If I understand correctly",
|
|
120
|
+
"If I'm not mistaken",
|
|
121
|
+
"Unless I'm wrong",
|
|
122
|
+
"Assuming that",
|
|
123
|
+
"Depending on",
|
|
124
|
+
|
|
125
|
+
// Exploration language
|
|
126
|
+
"Let me try",
|
|
127
|
+
"We could try",
|
|
128
|
+
"One option might be",
|
|
129
|
+
"Worth trying",
|
|
130
|
+
"Experiment with",
|
|
131
|
+
|
|
132
|
+
// Risk indicators
|
|
133
|
+
"Risky",
|
|
134
|
+
"Potentially problematic",
|
|
135
|
+
"Might break",
|
|
136
|
+
"Could cause issues",
|
|
137
|
+
"Watch out for"
|
|
138
|
+
];
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Question markers - indicate the model needs more info.
|
|
142
|
+
*/
|
|
143
|
+
const QUESTION_MARKERS = [
|
|
144
|
+
"Could you clarify",
|
|
145
|
+
"Can you confirm",
|
|
146
|
+
"Do you want",
|
|
147
|
+
"Would you like",
|
|
148
|
+
"Should I",
|
|
149
|
+
"Which approach",
|
|
150
|
+
"What do you prefer",
|
|
151
|
+
"Is this what you meant",
|
|
152
|
+
"Am I understanding correctly"
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Confidence levels.
|
|
157
|
+
*/
|
|
158
|
+
const CONFIDENCE_LEVELS = {
|
|
159
|
+
HIGH: 'high',
|
|
160
|
+
MEDIUM: 'medium',
|
|
161
|
+
LOW: 'low',
|
|
162
|
+
NEEDS_CLARIFICATION: 'needs_clarification'
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Default gate confidence configuration.
|
|
167
|
+
*/
|
|
168
|
+
const DEFAULT_GATE_CONFIG = {
|
|
169
|
+
enabled: true,
|
|
170
|
+
autoApplyThreshold: 0.7,
|
|
171
|
+
requireApprovalThreshold: 0.5,
|
|
172
|
+
blockThreshold: 0.3,
|
|
173
|
+
trackHistory: true,
|
|
174
|
+
maxHistoryEntries: 100
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
// ============================================================
|
|
178
|
+
// State
|
|
179
|
+
// ============================================================
|
|
180
|
+
|
|
181
|
+
const STATE_PATH = path.join(PROJECT_ROOT, '.workflow', 'state', 'gate-confidence.json');
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Get default confidence state.
|
|
185
|
+
* @returns {Object} Default state
|
|
186
|
+
*/
|
|
187
|
+
function getDefaultState() {
|
|
188
|
+
return {
|
|
189
|
+
history: [],
|
|
190
|
+
stats: {
|
|
191
|
+
totalAnalyzed: 0,
|
|
192
|
+
byLevel: {
|
|
193
|
+
high: 0,
|
|
194
|
+
medium: 0,
|
|
195
|
+
low: 0,
|
|
196
|
+
needs_clarification: 0
|
|
197
|
+
},
|
|
198
|
+
autoApplied: 0,
|
|
199
|
+
manualApproved: 0,
|
|
200
|
+
blocked: 0
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
let confidenceState = getDefaultState();
|
|
206
|
+
|
|
207
|
+
// ============================================================
|
|
208
|
+
// Configuration
|
|
209
|
+
// ============================================================
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Get gate confidence configuration from config.json with defaults.
|
|
213
|
+
* @returns {Object} Gate confidence configuration
|
|
214
|
+
*/
|
|
215
|
+
function getGateConfig() {
|
|
216
|
+
const config = getConfig();
|
|
217
|
+
return {
|
|
218
|
+
...DEFAULT_GATE_CONFIG,
|
|
219
|
+
...(config.gateConfidence || {})
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// ============================================================
|
|
224
|
+
// State Management
|
|
225
|
+
// ============================================================
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Load confidence state from file using safe JSON parsing.
|
|
229
|
+
*/
|
|
230
|
+
function loadState() {
|
|
231
|
+
if (fs.existsSync(STATE_PATH)) {
|
|
232
|
+
const loaded = safeJsonParse(STATE_PATH, null);
|
|
233
|
+
if (loaded && typeof loaded === 'object') {
|
|
234
|
+
const defaults = getDefaultState();
|
|
235
|
+
// Validate structure before using
|
|
236
|
+
confidenceState = {
|
|
237
|
+
history: Array.isArray(loaded.history) ? loaded.history : [],
|
|
238
|
+
stats: {
|
|
239
|
+
...defaults.stats,
|
|
240
|
+
...(loaded.stats || {}),
|
|
241
|
+
byLevel: { ...defaults.stats.byLevel, ...(loaded.stats?.byLevel || {}) }
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Save confidence state to file.
|
|
250
|
+
*/
|
|
251
|
+
function saveState() {
|
|
252
|
+
try {
|
|
253
|
+
const dir = path.dirname(STATE_PATH);
|
|
254
|
+
if (!fs.existsSync(dir)) {
|
|
255
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
256
|
+
}
|
|
257
|
+
fs.writeFileSync(STATE_PATH, JSON.stringify(confidenceState, null, 2));
|
|
258
|
+
} catch (err) {
|
|
259
|
+
warn(`Could not save confidence state: ${err.message}`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// ============================================================
|
|
264
|
+
// Confidence Analysis
|
|
265
|
+
// ============================================================
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Analyze text for confidence level.
|
|
269
|
+
* @param {string} text - Text to analyze
|
|
270
|
+
* @param {Object} options - Analysis options
|
|
271
|
+
* @returns {Object} Confidence analysis result
|
|
272
|
+
*/
|
|
273
|
+
function analyzeConfidence(text, options = {}) {
|
|
274
|
+
if (!text || typeof text !== 'string') {
|
|
275
|
+
return {
|
|
276
|
+
level: CONFIDENCE_LEVELS.LOW,
|
|
277
|
+
score: 0,
|
|
278
|
+
error: 'Invalid input'
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const textLower = text.toLowerCase();
|
|
283
|
+
const analysis = {
|
|
284
|
+
highMarkers: [],
|
|
285
|
+
lowMarkers: [],
|
|
286
|
+
questionMarkers: [],
|
|
287
|
+
segments: []
|
|
288
|
+
};
|
|
289
|
+
|
|
290
|
+
// Find high confidence markers
|
|
291
|
+
for (const marker of HIGH_CONFIDENCE_MARKERS) {
|
|
292
|
+
if (textLower.includes(marker.toLowerCase())) {
|
|
293
|
+
analysis.highMarkers.push(marker);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Find low confidence markers
|
|
298
|
+
for (const marker of LOW_CONFIDENCE_MARKERS) {
|
|
299
|
+
if (textLower.includes(marker.toLowerCase())) {
|
|
300
|
+
analysis.lowMarkers.push(marker);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Find question markers
|
|
305
|
+
for (const marker of QUESTION_MARKERS) {
|
|
306
|
+
if (textLower.includes(marker.toLowerCase())) {
|
|
307
|
+
analysis.questionMarkers.push(marker);
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Calculate base score using normalized weights to prevent unbounded values
|
|
312
|
+
const totalMarkers = analysis.highMarkers.length + analysis.lowMarkers.length + analysis.questionMarkers.length;
|
|
313
|
+
|
|
314
|
+
let score;
|
|
315
|
+
if (totalMarkers === 0) {
|
|
316
|
+
// No markers found - neutral score
|
|
317
|
+
score = 0.5;
|
|
318
|
+
} else {
|
|
319
|
+
// Normalize weights based on total markers found (max influence capped)
|
|
320
|
+
const highInfluence = Math.min(analysis.highMarkers.length, 5) * 0.08; // Max +0.4
|
|
321
|
+
const lowInfluence = Math.min(analysis.lowMarkers.length, 5) * -0.1; // Max -0.5
|
|
322
|
+
const questionInfluence = Math.min(analysis.questionMarkers.length, 3) * -0.12; // Max -0.36
|
|
323
|
+
|
|
324
|
+
// Start from neutral (0.5) and adjust
|
|
325
|
+
score = 0.5 + highInfluence + lowInfluence + questionInfluence;
|
|
326
|
+
|
|
327
|
+
// Clamp to 0-1
|
|
328
|
+
score = Math.max(0, Math.min(1, score));
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// Determine level
|
|
332
|
+
let level;
|
|
333
|
+
if (analysis.questionMarkers.length > 0) {
|
|
334
|
+
level = CONFIDENCE_LEVELS.NEEDS_CLARIFICATION;
|
|
335
|
+
} else if (score >= 0.7) {
|
|
336
|
+
level = CONFIDENCE_LEVELS.HIGH;
|
|
337
|
+
} else if (score >= 0.4) {
|
|
338
|
+
level = CONFIDENCE_LEVELS.MEDIUM;
|
|
339
|
+
} else {
|
|
340
|
+
level = CONFIDENCE_LEVELS.LOW;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// Analyze specific segments for more granular scoring
|
|
344
|
+
analysis.segments = analyzeSegments(text);
|
|
345
|
+
|
|
346
|
+
// Adjust score based on segment analysis
|
|
347
|
+
const segmentScores = analysis.segments.map(s => s.confidence);
|
|
348
|
+
if (segmentScores.length > 0) {
|
|
349
|
+
const avgSegmentScore = segmentScores.reduce((a, b) => a + b, 0) / segmentScores.length;
|
|
350
|
+
score = (score + avgSegmentScore) / 2; // Blend marker and segment scores
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const result = {
|
|
354
|
+
level,
|
|
355
|
+
score: Math.round(score * 100) / 100,
|
|
356
|
+
markers: {
|
|
357
|
+
high: analysis.highMarkers,
|
|
358
|
+
low: analysis.lowMarkers,
|
|
359
|
+
questions: analysis.questionMarkers
|
|
360
|
+
},
|
|
361
|
+
segments: analysis.segments,
|
|
362
|
+
recommendation: getRecommendation(level, score),
|
|
363
|
+
timestamp: new Date().toISOString()
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
// Track in history if enabled
|
|
367
|
+
const config = getGateConfig();
|
|
368
|
+
if (config.trackHistory && options.track !== false) {
|
|
369
|
+
loadState();
|
|
370
|
+
confidenceState.stats.totalAnalyzed++;
|
|
371
|
+
confidenceState.stats.byLevel[level]++;
|
|
372
|
+
confidenceState.history.push({
|
|
373
|
+
score,
|
|
374
|
+
level,
|
|
375
|
+
timestamp: result.timestamp,
|
|
376
|
+
textPreview: text.slice(0, 100) + (text.length > 100 ? '...' : '')
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
// Keep only recent history
|
|
380
|
+
if (confidenceState.history.length > config.maxHistoryEntries) {
|
|
381
|
+
confidenceState.history = confidenceState.history.slice(-config.maxHistoryEntries);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
saveState();
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return result;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Analyze text segments for confidence.
|
|
392
|
+
* @param {string} text - Text to analyze
|
|
393
|
+
* @returns {Array} Segment analysis
|
|
394
|
+
*/
|
|
395
|
+
function analyzeSegments(text) {
|
|
396
|
+
const segments = [];
|
|
397
|
+
|
|
398
|
+
// Split into paragraphs/sections
|
|
399
|
+
const paragraphs = text.split(/\n\n+/).filter(p => p.trim().length > 0);
|
|
400
|
+
|
|
401
|
+
for (let i = 0; i < paragraphs.length; i++) {
|
|
402
|
+
const paragraph = paragraphs[i].trim();
|
|
403
|
+
|
|
404
|
+
// Detect code blocks
|
|
405
|
+
if (paragraph.startsWith('```') || paragraph.startsWith(' ')) {
|
|
406
|
+
segments.push({
|
|
407
|
+
type: 'code',
|
|
408
|
+
confidence: 0.8, // Code blocks are generally confident
|
|
409
|
+
preview: paragraph.slice(0, 50)
|
|
410
|
+
});
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Analyze paragraph confidence
|
|
415
|
+
let confidence = 0.5;
|
|
416
|
+
|
|
417
|
+
// Check for hedging at start of paragraph
|
|
418
|
+
if (/^(I think|Maybe|Perhaps|Possibly|It might)/i.test(paragraph)) {
|
|
419
|
+
confidence -= 0.2;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Check for confident starts
|
|
423
|
+
if (/^(This will|Here's|The solution|To fix)/i.test(paragraph)) {
|
|
424
|
+
confidence += 0.2;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Check for explanations (usually confident)
|
|
428
|
+
if (/because|since|therefore|as a result/i.test(paragraph)) {
|
|
429
|
+
confidence += 0.1;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
// Check for warnings/caveats
|
|
433
|
+
if (/warning|caution|note:|important:|be careful/i.test(paragraph)) {
|
|
434
|
+
confidence -= 0.1; // Not necessarily low confidence, but cautionary
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
segments.push({
|
|
438
|
+
type: 'text',
|
|
439
|
+
confidence: Math.max(0, Math.min(1, confidence)),
|
|
440
|
+
preview: paragraph.slice(0, 50)
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
return segments;
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Get recommendation based on confidence.
|
|
449
|
+
* @param {string} level - Confidence level
|
|
450
|
+
* @param {number} score - Confidence score
|
|
451
|
+
* @returns {Object} Recommendation
|
|
452
|
+
*/
|
|
453
|
+
function getRecommendation(level, score) {
|
|
454
|
+
const config = getGateConfig();
|
|
455
|
+
|
|
456
|
+
if (level === CONFIDENCE_LEVELS.NEEDS_CLARIFICATION) {
|
|
457
|
+
return {
|
|
458
|
+
action: 'ask',
|
|
459
|
+
message: 'The response contains questions - clarification needed before proceeding',
|
|
460
|
+
autoApply: false
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
if (score >= config.autoApplyThreshold) {
|
|
465
|
+
return {
|
|
466
|
+
action: 'auto-apply',
|
|
467
|
+
message: 'High confidence - safe to apply automatically',
|
|
468
|
+
autoApply: true
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
if (score >= config.requireApprovalThreshold) {
|
|
473
|
+
return {
|
|
474
|
+
action: 'approve',
|
|
475
|
+
message: 'Medium confidence - review before applying',
|
|
476
|
+
autoApply: false
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
if (score >= config.blockThreshold) {
|
|
481
|
+
return {
|
|
482
|
+
action: 'review',
|
|
483
|
+
message: 'Low confidence - careful review recommended',
|
|
484
|
+
autoApply: false
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
return {
|
|
489
|
+
action: 'block',
|
|
490
|
+
message: 'Very low confidence - do not apply without verification',
|
|
491
|
+
autoApply: false
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// ============================================================
|
|
496
|
+
// Quality Gate Integration
|
|
497
|
+
// ============================================================
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Check if a response should be auto-applied.
|
|
501
|
+
* @param {string} response - AI response text
|
|
502
|
+
* @returns {Object} Gate check result
|
|
503
|
+
*/
|
|
504
|
+
function checkGate(response) {
|
|
505
|
+
const analysis = analyzeConfidence(response);
|
|
506
|
+
const config = getGateConfig();
|
|
507
|
+
|
|
508
|
+
return {
|
|
509
|
+
passed: analysis.score >= config.autoApplyThreshold,
|
|
510
|
+
confidence: analysis,
|
|
511
|
+
action: analysis.recommendation.action,
|
|
512
|
+
requiresApproval: !analysis.recommendation.autoApply
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Valid decision types for recordDecision.
|
|
518
|
+
*/
|
|
519
|
+
const VALID_DECISIONS = ['auto-apply', 'approved', 'blocked'];
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* Record a gate decision.
|
|
523
|
+
* @param {Object} params - Decision parameters
|
|
524
|
+
* @throws {Error} If decision is not a valid type
|
|
525
|
+
*/
|
|
526
|
+
function recordDecision({ analysisId, decision, outcome }) {
|
|
527
|
+
// Validate decision type to prevent silent failures
|
|
528
|
+
if (!VALID_DECISIONS.includes(decision)) {
|
|
529
|
+
throw new Error(`Invalid decision type: ${decision}. Must be one of: ${VALID_DECISIONS.join(', ')}`);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
loadState();
|
|
533
|
+
|
|
534
|
+
switch (decision) {
|
|
535
|
+
case 'auto-apply':
|
|
536
|
+
confidenceState.stats.autoApplied++;
|
|
537
|
+
break;
|
|
538
|
+
case 'approved':
|
|
539
|
+
confidenceState.stats.manualApproved++;
|
|
540
|
+
break;
|
|
541
|
+
case 'blocked':
|
|
542
|
+
confidenceState.stats.blocked++;
|
|
543
|
+
break;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
saveState();
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// ============================================================
|
|
550
|
+
// Statistics
|
|
551
|
+
// ============================================================
|
|
552
|
+
|
|
553
|
+
/**
|
|
554
|
+
* Get confidence statistics.
|
|
555
|
+
* @returns {Object} Statistics
|
|
556
|
+
*/
|
|
557
|
+
function getStats() {
|
|
558
|
+
loadState();
|
|
559
|
+
|
|
560
|
+
const stats = { ...confidenceState.stats };
|
|
561
|
+
|
|
562
|
+
// Calculate additional metrics
|
|
563
|
+
const total = stats.totalAnalyzed || 1;
|
|
564
|
+
stats.percentages = {
|
|
565
|
+
high: ((stats.byLevel.high / total) * 100).toFixed(1),
|
|
566
|
+
medium: ((stats.byLevel.medium / total) * 100).toFixed(1),
|
|
567
|
+
low: ((stats.byLevel.low / total) * 100).toFixed(1),
|
|
568
|
+
needs_clarification: ((stats.byLevel.needs_clarification / total) * 100).toFixed(1)
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
// Calculate average score from history
|
|
572
|
+
if (confidenceState.history.length > 0) {
|
|
573
|
+
const scores = confidenceState.history.map(h => h.score);
|
|
574
|
+
stats.averageScore = (scores.reduce((a, b) => a + b, 0) / scores.length).toFixed(2);
|
|
575
|
+
stats.recentTrend = calculateTrend(confidenceState.history.slice(-20));
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
return stats;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* Calculate confidence trend.
|
|
583
|
+
* @param {Array} history - Recent history entries
|
|
584
|
+
* @returns {string} Trend direction
|
|
585
|
+
*/
|
|
586
|
+
function calculateTrend(history) {
|
|
587
|
+
if (history.length < 5) return 'insufficient_data';
|
|
588
|
+
|
|
589
|
+
const firstHalf = history.slice(0, Math.floor(history.length / 2));
|
|
590
|
+
const secondHalf = history.slice(Math.floor(history.length / 2));
|
|
591
|
+
|
|
592
|
+
const firstAvg = firstHalf.reduce((a, b) => a + b.score, 0) / firstHalf.length;
|
|
593
|
+
const secondAvg = secondHalf.reduce((a, b) => a + b.score, 0) / secondHalf.length;
|
|
594
|
+
|
|
595
|
+
const diff = secondAvg - firstAvg;
|
|
596
|
+
|
|
597
|
+
if (diff > 0.1) return 'improving';
|
|
598
|
+
if (diff < -0.1) return 'declining';
|
|
599
|
+
return 'stable';
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
// ============================================================
|
|
603
|
+
// CLI Output
|
|
604
|
+
// ============================================================
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Print confidence analysis.
|
|
608
|
+
* @param {Object} analysis - Analysis result
|
|
609
|
+
*/
|
|
610
|
+
function printAnalysis(analysis) {
|
|
611
|
+
printHeader('CONFIDENCE ANALYSIS');
|
|
612
|
+
|
|
613
|
+
// Score visualization
|
|
614
|
+
const scoreBar = '█'.repeat(Math.round(analysis.score * 20));
|
|
615
|
+
const emptyBar = '░'.repeat(20 - Math.round(analysis.score * 20));
|
|
616
|
+
|
|
617
|
+
const levelColor = analysis.level === 'high' ? success :
|
|
618
|
+
analysis.level === 'medium' ? warn :
|
|
619
|
+
analysis.level === 'low' ? error : info;
|
|
620
|
+
|
|
621
|
+
printSection('Score');
|
|
622
|
+
console.log(` ${scoreBar}${emptyBar} ${(analysis.score * 100).toFixed(0)}%`);
|
|
623
|
+
console.log(` Level: ${levelColor(analysis.level.toUpperCase())}`);
|
|
624
|
+
|
|
625
|
+
printSection('Markers Found');
|
|
626
|
+
if (analysis.markers.high.length > 0) {
|
|
627
|
+
console.log(` ${success('High confidence:')} ${analysis.markers.high.slice(0, 3).join(', ')}`);
|
|
628
|
+
}
|
|
629
|
+
if (analysis.markers.low.length > 0) {
|
|
630
|
+
console.log(` ${warn('Low confidence:')} ${analysis.markers.low.slice(0, 3).join(', ')}`);
|
|
631
|
+
}
|
|
632
|
+
if (analysis.markers.questions.length > 0) {
|
|
633
|
+
console.log(` ${info('Questions:')} ${analysis.markers.questions.slice(0, 3).join(', ')}`);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
if (analysis.markers.high.length === 0 &&
|
|
637
|
+
analysis.markers.low.length === 0 &&
|
|
638
|
+
analysis.markers.questions.length === 0) {
|
|
639
|
+
console.log(color('dim', ' No specific markers found'));
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
printSection('Recommendation');
|
|
643
|
+
const actionIcon = analysis.recommendation.action === 'auto-apply' ? '✓' :
|
|
644
|
+
analysis.recommendation.action === 'approve' ? '?' :
|
|
645
|
+
analysis.recommendation.action === 'ask' ? '❓' : '✗';
|
|
646
|
+
console.log(` ${actionIcon} ${analysis.recommendation.message}`);
|
|
647
|
+
console.log(` ${color('dim', 'Auto-apply:')} ${analysis.recommendation.autoApply ? 'Yes' : 'No'}`);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
/**
|
|
651
|
+
* Print statistics.
|
|
652
|
+
*/
|
|
653
|
+
function printStats() {
|
|
654
|
+
const stats = getStats();
|
|
655
|
+
|
|
656
|
+
printHeader('CONFIDENCE STATISTICS');
|
|
657
|
+
|
|
658
|
+
printSection('Overview');
|
|
659
|
+
console.log(` ${color('dim', 'Total analyzed:')} ${stats.totalAnalyzed}`);
|
|
660
|
+
if (stats.averageScore) {
|
|
661
|
+
console.log(` ${color('dim', 'Average score:')} ${(stats.averageScore * 100).toFixed(0)}%`);
|
|
662
|
+
console.log(` ${color('dim', 'Recent trend:')} ${stats.recentTrend}`);
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
printSection('Distribution');
|
|
666
|
+
console.log(` ${success('High:')} ${stats.byLevel.high} (${stats.percentages.high}%)`);
|
|
667
|
+
console.log(` ${warn('Medium:')} ${stats.byLevel.medium} (${stats.percentages.medium}%)`);
|
|
668
|
+
console.log(` ${error('Low:')} ${stats.byLevel.low} (${stats.percentages.low}%)`);
|
|
669
|
+
console.log(` ${info('Needs clarification:')} ${stats.byLevel.needs_clarification} (${stats.percentages.needs_clarification}%)`);
|
|
670
|
+
|
|
671
|
+
printSection('Decisions');
|
|
672
|
+
console.log(` ${color('dim', 'Auto-applied:')} ${stats.autoApplied}`);
|
|
673
|
+
console.log(` ${color('dim', 'Manual approved:')} ${stats.manualApproved}`);
|
|
674
|
+
console.log(` ${color('dim', 'Blocked:')} ${stats.blocked}`);
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// ============================================================
|
|
678
|
+
// Exports
|
|
679
|
+
// ============================================================
|
|
680
|
+
|
|
681
|
+
module.exports = {
|
|
682
|
+
// Core functions
|
|
683
|
+
analyzeConfidence,
|
|
684
|
+
checkGate,
|
|
685
|
+
recordDecision,
|
|
686
|
+
getStats,
|
|
687
|
+
|
|
688
|
+
// Configuration
|
|
689
|
+
getGateConfig,
|
|
690
|
+
CONFIDENCE_LEVELS,
|
|
691
|
+
HIGH_CONFIDENCE_MARKERS,
|
|
692
|
+
LOW_CONFIDENCE_MARKERS,
|
|
693
|
+
QUESTION_MARKERS,
|
|
694
|
+
DEFAULT_GATE_CONFIG
|
|
695
|
+
};
|
|
696
|
+
|
|
697
|
+
// ============================================================
|
|
698
|
+
// CLI Entry Point
|
|
699
|
+
// ============================================================
|
|
700
|
+
|
|
701
|
+
function main() {
|
|
702
|
+
const { positional, flags } = parseFlags(process.argv.slice(2));
|
|
703
|
+
const command = positional[0];
|
|
704
|
+
|
|
705
|
+
if (flags.help || !command) {
|
|
706
|
+
console.log(`
|
|
707
|
+
Usage: flow confidence <command> [options]
|
|
708
|
+
|
|
709
|
+
Commands:
|
|
710
|
+
analyze "<text>" Analyze text for confidence level
|
|
711
|
+
check --file <f> Check confidence of file contents
|
|
712
|
+
stats Show confidence statistics
|
|
713
|
+
reset Reset statistics
|
|
714
|
+
|
|
715
|
+
Options:
|
|
716
|
+
--json Output as JSON
|
|
717
|
+
--no-track Don't track in history
|
|
718
|
+
--help Show this help
|
|
719
|
+
|
|
720
|
+
Examples:
|
|
721
|
+
flow confidence analyze "I think this might work, but I'm not sure"
|
|
722
|
+
flow confidence analyze "This is the correct solution. Here's the fix:"
|
|
723
|
+
flow confidence check --file response.txt
|
|
724
|
+
flow confidence stats
|
|
725
|
+
`);
|
|
726
|
+
return;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
switch (command) {
|
|
730
|
+
case 'analyze': {
|
|
731
|
+
const text = positional.slice(1).join(' ') || flags.text;
|
|
732
|
+
|
|
733
|
+
if (!text) {
|
|
734
|
+
error('Please provide text to analyze');
|
|
735
|
+
process.exit(1);
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// Input length validation (prevent DoS)
|
|
739
|
+
if (text.length > 50000) {
|
|
740
|
+
error('Input text exceeds maximum length (50000 chars)');
|
|
741
|
+
process.exit(1);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
const analysis = analyzeConfidence(text, { track: !flags['no-track'] });
|
|
745
|
+
|
|
746
|
+
if (flags.json) {
|
|
747
|
+
outputJson(analysis);
|
|
748
|
+
} else {
|
|
749
|
+
printAnalysis(analysis);
|
|
750
|
+
}
|
|
751
|
+
break;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
case 'check': {
|
|
755
|
+
const file = flags.file || positional[1];
|
|
756
|
+
|
|
757
|
+
if (!file) {
|
|
758
|
+
error('Please provide a file with --file');
|
|
759
|
+
process.exit(1);
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// Validate path is within project directory (prevent path traversal)
|
|
763
|
+
const filePath = path.resolve(file);
|
|
764
|
+
if (!filePath.startsWith(PROJECT_ROOT)) {
|
|
765
|
+
error('File must be within project directory');
|
|
766
|
+
process.exit(1);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
if (!fs.existsSync(filePath)) {
|
|
770
|
+
error('File not found');
|
|
771
|
+
process.exit(1);
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
let content;
|
|
775
|
+
try {
|
|
776
|
+
content = fs.readFileSync(filePath, 'utf8');
|
|
777
|
+
} catch (err) {
|
|
778
|
+
error('Failed to read file');
|
|
779
|
+
process.exit(1);
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
const gateResult = checkGate(content);
|
|
783
|
+
|
|
784
|
+
if (flags.json) {
|
|
785
|
+
outputJson(gateResult);
|
|
786
|
+
} else {
|
|
787
|
+
printAnalysis(gateResult.confidence);
|
|
788
|
+
console.log('');
|
|
789
|
+
console.log(`Gate: ${gateResult.passed ? success('PASSED') : warn('REQUIRES APPROVAL')}`);
|
|
790
|
+
}
|
|
791
|
+
break;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
case 'stats':
|
|
795
|
+
if (flags.json) {
|
|
796
|
+
outputJson(getStats());
|
|
797
|
+
} else {
|
|
798
|
+
printStats();
|
|
799
|
+
}
|
|
800
|
+
break;
|
|
801
|
+
|
|
802
|
+
case 'reset':
|
|
803
|
+
confidenceState = {
|
|
804
|
+
history: [],
|
|
805
|
+
stats: {
|
|
806
|
+
totalAnalyzed: 0,
|
|
807
|
+
byLevel: { high: 0, medium: 0, low: 0, needs_clarification: 0 },
|
|
808
|
+
autoApplied: 0,
|
|
809
|
+
manualApproved: 0,
|
|
810
|
+
blocked: 0
|
|
811
|
+
}
|
|
812
|
+
};
|
|
813
|
+
saveState();
|
|
814
|
+
success('Statistics reset');
|
|
815
|
+
break;
|
|
816
|
+
|
|
817
|
+
default:
|
|
818
|
+
error(`Unknown command: ${command}`);
|
|
819
|
+
process.exit(1);
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
if (require.main === module) {
|
|
824
|
+
main();
|
|
825
|
+
}
|