@hegel-dev/companion 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/README.md +84 -0
- package/dist/analyzers/prompt-analyzer.d.ts +7 -0
- package/dist/analyzers/prompt-analyzer.d.ts.map +1 -0
- package/dist/analyzers/prompt-analyzer.js +224 -0
- package/dist/analyzers/prompt-analyzer.js.map +1 -0
- package/dist/analyzers/response-analyzer.d.ts +6 -0
- package/dist/analyzers/response-analyzer.d.ts.map +1 -0
- package/dist/analyzers/response-analyzer.js +218 -0
- package/dist/analyzers/response-analyzer.js.map +1 -0
- package/dist/analyzers/session-analyzer.d.ts +10 -0
- package/dist/analyzers/session-analyzer.d.ts.map +1 -0
- package/dist/analyzers/session-analyzer.js +194 -0
- package/dist/analyzers/session-analyzer.js.map +1 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +27 -0
- package/dist/config.js.map +1 -0
- package/dist/debug-wrapper.d.ts +2 -0
- package/dist/debug-wrapper.d.ts.map +1 -0
- package/dist/debug-wrapper.js +55 -0
- package/dist/debug-wrapper.js.map +1 -0
- package/dist/dev-watch.d.ts +10 -0
- package/dist/dev-watch.d.ts.map +1 -0
- package/dist/dev-watch.js +55 -0
- package/dist/dev-watch.js.map +1 -0
- package/dist/format.d.ts +4 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +38 -0
- package/dist/format.js.map +1 -0
- package/dist/hook.d.ts +8 -0
- package/dist/hook.d.ts.map +1 -0
- package/dist/hook.js +320 -0
- package/dist/hook.js.map +1 -0
- package/dist/hooks-generator.d.ts +45 -0
- package/dist/hooks-generator.d.ts.map +1 -0
- package/dist/hooks-generator.js +120 -0
- package/dist/hooks-generator.js.map +1 -0
- package/dist/mcp.d.ts +10 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +173 -0
- package/dist/mcp.js.map +1 -0
- package/dist/prompts.d.ts +11 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +85 -0
- package/dist/prompts.js.map +1 -0
- package/dist/setup.d.ts +28 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +247 -0
- package/dist/setup.js.map +1 -0
- package/dist/state.d.ts +14 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +77 -0
- package/dist/state.js.map +1 -0
- package/dist/transcript.d.ts +32 -0
- package/dist/transcript.d.ts.map +1 -0
- package/dist/transcript.js +156 -0
- package/dist/transcript.js.map +1 -0
- package/dist/types.d.ts +137 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/hegel-vscode/hegel-companion-1.0.0.vsix +0 -0
- package/hegel.config.schema.json +63 -0
- package/package.json +59 -0
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Hegel Companion
|
|
2
|
+
|
|
3
|
+
**Dialectical companion for AI-assisted development.**
|
|
4
|
+
|
|
5
|
+
Hegel sits alongside your Cursor IDE sessions and provides real-time critical thinking oversight — catching lazy prompts, flagging overconfident AI responses, tracking session quality degradation, and nudging you to maintain engineering rigor.
|
|
6
|
+
|
|
7
|
+
Named after Georg Wilhelm Friedrich Hegel's dialectical method: every thesis (your prompt) deserves an antithesis (critical review) before reaching synthesis (better code).
|
|
8
|
+
|
|
9
|
+
## Two-Layer Analysis
|
|
10
|
+
|
|
11
|
+
### Layer 1: Fast Rule-Based Checks (command hooks)
|
|
12
|
+
Runs in milliseconds, zero cost. Always active.
|
|
13
|
+
|
|
14
|
+
- Detects vague/lazy prompts ("fix it", "do the same", single-word confirmations)
|
|
15
|
+
- Catches prompt quality degradation over the session
|
|
16
|
+
- Flags rapid-fire prompting without review pauses
|
|
17
|
+
- Tracks scope creep and untested changes
|
|
18
|
+
- Detects overconfident AI language and sycophancy patterns
|
|
19
|
+
- Session fatigue warnings
|
|
20
|
+
|
|
21
|
+
### Layer 2: LLM Deep Analysis (prompt hooks)
|
|
22
|
+
Uses your Cursor subscription models. Optional, configurable.
|
|
23
|
+
|
|
24
|
+
- Nuanced prompt quality evaluation beyond pattern matching
|
|
25
|
+
- Contextual assessment of whether a prompt has enough detail for its intent
|
|
26
|
+
- AI response review for missing edge cases, security blind spots, and scope creep
|
|
27
|
+
- Detects when you're blindly continuing from a previous AI response
|
|
28
|
+
|
|
29
|
+
## Setup
|
|
30
|
+
|
|
31
|
+
### Install via npm
|
|
32
|
+
|
|
33
|
+
Install the package and run the setup CLI from your Cursor project root:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm install --save-dev @hegel-dev/companion
|
|
37
|
+
npx hegel-companion init .
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Or, for a one-shot install without adding a dependency:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx @hegel-dev/companion init .
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
> **Note:** This package was previously published as `hegel-companion`. That name is now deprecated — use `@hegel-dev/companion` for new installs. The CLI command (`hegel-companion`) is unchanged.
|
|
47
|
+
|
|
48
|
+
This single command will:
|
|
49
|
+
1. Generate `.cursor/hooks.json` to wire up the analysis layers.
|
|
50
|
+
2. Scaffold a default `hegel.config.json` in your project root.
|
|
51
|
+
3. Register the `hegel-mcp` server in `.cursor/mcp.json`.
|
|
52
|
+
4. Install the Hegel Cursor extension for the sidebar dashboard.
|
|
53
|
+
5. Add a `.cursor/rules/hegel-companion.mdc` rule so the AI knows how to use the MCP tools.
|
|
54
|
+
|
|
55
|
+
### Configure
|
|
56
|
+
|
|
57
|
+
The easiest way to configure Hegel is through the **Cursor Settings UI**:
|
|
58
|
+
|
|
59
|
+
1. Open Settings (`Cmd/Ctrl + ,`)
|
|
60
|
+
2. Search for **"Hegel"**
|
|
61
|
+
3. Adjust your model, strictness, and other preferences.
|
|
62
|
+
|
|
63
|
+
These settings automatically sync to a `hegel.config.json` file in your project root, which you can commit to version control to share team-wide standards.
|
|
64
|
+
|
|
65
|
+
*(Note: Configuration changes are automatically detected when you start a new chat session).*
|
|
66
|
+
|
|
67
|
+
## Architecture
|
|
68
|
+
|
|
69
|
+
Hegel operates as a local, privacy-first system:
|
|
70
|
+
- **Hooks**: Intercepts prompts and responses via Cursor's `.cursor/hooks.json`.
|
|
71
|
+
- **State**: Session state is stored locally in `.hegel-state/` as JSON files.
|
|
72
|
+
- **MCP Server**: Provides `hegel-status` and `hegel-review` tools to the AI.
|
|
73
|
+
- **Cursor Extension**: Reads the local state to power the sidebar dashboard and status bar.
|
|
74
|
+
|
|
75
|
+
## Philosophy
|
|
76
|
+
|
|
77
|
+
> "The owl of Minerva spreads its wings only with the falling of the dusk."
|
|
78
|
+
> — Hegel, *Philosophy of Right*
|
|
79
|
+
|
|
80
|
+
Unlike Minerva's owl, Hegel doesn't wait for dusk. It watches in real time, helping you think critically *during* the creative process, not only in retrospect.
|
|
81
|
+
|
|
82
|
+
## License
|
|
83
|
+
|
|
84
|
+
MIT
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Concern, SessionState, PromptRecord, TranscriptContext } from "../types.js";
|
|
2
|
+
export declare function analyzePrompt(prompt: string, state: SessionState, transcript?: TranscriptContext | null): {
|
|
3
|
+
concerns: Concern[];
|
|
4
|
+
shouldBlock: boolean;
|
|
5
|
+
};
|
|
6
|
+
export declare function buildPromptRecord(prompt: string, concerns: Concern[]): PromptRecord;
|
|
7
|
+
//# sourceMappingURL=prompt-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/prompt-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAgC1F,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,YAAY,EACnB,UAAU,CAAC,EAAE,iBAAiB,GAAG,IAAI,GACpC;IAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CA4L/C;AAmBD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,OAAO,EAAE,GAClB,YAAY,CAOd"}
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import { recentPrompts, sessionDurationMinutes } from "../state.js";
|
|
2
|
+
import { isContextualFollowUp, lastResponseInvitesFollowUp, recentUserTurns } from "../transcript.js";
|
|
3
|
+
// ── Pattern Definitions ──
|
|
4
|
+
const LAZY_PATTERNS = [
|
|
5
|
+
{ pattern: /^(fix it|fix this|do it|make it work|same thing|again)\.?$/i, label: "extremely vague directive" },
|
|
6
|
+
{ pattern: /^(yes|no|ok|sure|go ahead|yep|yeah|continue|proceed)\.?$/i, label: "single-word confirmation without context" },
|
|
7
|
+
{ pattern: /^do the same (for|with|to)/i, label: "'do the same' without specifying what" },
|
|
8
|
+
{ pattern: /^(now do|and also|next)\b.{0,20}$/i, label: "short chained request lacking self-contained context" },
|
|
9
|
+
];
|
|
10
|
+
const MISSING_CONTEXT_SIGNALS = [
|
|
11
|
+
{ test: (p) => p.length < 15 && !p.includes("?"), message: "Very short prompt without a question — the AI will guess your intent" },
|
|
12
|
+
{ test: (p) => /\b(it|this|that|these|those)\b/i.test(p) && p.split(/\s+/).length < 8, message: "Pronoun-heavy short prompt — 'it'/'this' may be ambiguous after context compaction" },
|
|
13
|
+
];
|
|
14
|
+
const ACCEPTANCE_CRITERIA_HINTS = [
|
|
15
|
+
/\b(implement|create|build|add|write|refactor|migrate|redesign)\b/i,
|
|
16
|
+
];
|
|
17
|
+
const HAS_CRITERIA = [
|
|
18
|
+
/\b(should|must|ensure|verify|test|expect|accept|criteria|requirement)\b/i,
|
|
19
|
+
/\b(when|if|unless|given|then)\b/i,
|
|
20
|
+
/\d+/, // numbers often indicate concrete specs
|
|
21
|
+
];
|
|
22
|
+
const OPERATIONAL_FOLLOW_UP = /\b(commit|push|open pr|pull request|run tests?|test suite|coverage|build|review findings|update status|continue with|proceed with|release)\b/i;
|
|
23
|
+
// ── Analyzer ──
|
|
24
|
+
export function analyzePrompt(prompt, state, transcript) {
|
|
25
|
+
const concerns = [];
|
|
26
|
+
const words = prompt.trim().split(/\s+/);
|
|
27
|
+
const wc = words.length;
|
|
28
|
+
const ctx = transcript ?? null;
|
|
29
|
+
// When a transcript is available, determine whether this prompt is a
|
|
30
|
+
// natural follow-up to the preceding assistant response. This single
|
|
31
|
+
// flag gates most of the false-positive suppression below.
|
|
32
|
+
const isFollowUp = ctx ? isContextualFollowUp(prompt, ctx) : false;
|
|
33
|
+
const responseInvitedThis = ctx ? lastResponseInvitesFollowUp(ctx) : false;
|
|
34
|
+
const isOperationalFollowUp = OPERATIONAL_FOLLOW_UP.test(prompt);
|
|
35
|
+
const isFileReference = /^@\S+/.test(prompt.trim()) || prompt.includes("```");
|
|
36
|
+
// 1. Lazy/vague prompt detection
|
|
37
|
+
// Suppress when the assistant just asked a question or presented options
|
|
38
|
+
// and the user is responding with a short affirmative/directive.
|
|
39
|
+
for (const { pattern, label } of LAZY_PATTERNS) {
|
|
40
|
+
if (pattern.test(prompt.trim())) {
|
|
41
|
+
if (isFollowUp || responseInvitedThis) {
|
|
42
|
+
concerns.push({
|
|
43
|
+
severity: "info",
|
|
44
|
+
category: "prompt-quality",
|
|
45
|
+
message: `Short directive ("${prompt.trim().slice(0, 40)}") — appears to be a contextual follow-up`,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
concerns.push({
|
|
50
|
+
severity: "warning",
|
|
51
|
+
category: "prompt-quality",
|
|
52
|
+
message: `Lazy prompt detected: ${label}`,
|
|
53
|
+
suggestion: "Rewrite with specific intent, context, and expected outcome. What exactly should change, and how will you verify it worked?",
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// 2. Missing context signals
|
|
59
|
+
// Suppress pronoun-heavy warning when pronouns clearly refer to the
|
|
60
|
+
// assistant's last response (transcript available and follow-up detected).
|
|
61
|
+
for (const { test, message } of MISSING_CONTEXT_SIGNALS) {
|
|
62
|
+
if (test(prompt)) {
|
|
63
|
+
if (isFollowUp)
|
|
64
|
+
continue;
|
|
65
|
+
concerns.push({
|
|
66
|
+
severity: "info",
|
|
67
|
+
category: "prompt-quality",
|
|
68
|
+
message,
|
|
69
|
+
suggestion: "Add explicit references to files, functions, or behaviors instead of relying on pronouns.",
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// 3. Significant task without acceptance criteria
|
|
74
|
+
const isSignificantTask = ACCEPTANCE_CRITERIA_HINTS.some((r) => r.test(prompt));
|
|
75
|
+
const hasCriteria = HAS_CRITERIA.some((r) => r.test(prompt));
|
|
76
|
+
if (isSignificantTask && !hasCriteria && wc > 5) {
|
|
77
|
+
concerns.push({
|
|
78
|
+
severity: "info",
|
|
79
|
+
category: "missing-criteria",
|
|
80
|
+
message: "Task request without acceptance criteria",
|
|
81
|
+
suggestion: "Consider adding: what 'done' looks like, edge cases to handle, or how to verify the result.",
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
// 4. Prompt quality degradation over the session
|
|
85
|
+
// With a transcript, use actual user turn word counts for a more accurate
|
|
86
|
+
// comparison than the state-tracked PromptRecords (which only start
|
|
87
|
+
// tracking once the hook is installed).
|
|
88
|
+
const recent = recentPrompts(state, 5);
|
|
89
|
+
// Cap individual prompt word counts at 100 to prevent massive error logs
|
|
90
|
+
// from artificially inflating the average and causing false positives.
|
|
91
|
+
const capWc = (count) => Math.min(count, 100);
|
|
92
|
+
if (ctx && ctx.userTurnCount >= 4) {
|
|
93
|
+
const userTurns = recentUserTurns(ctx, 6);
|
|
94
|
+
if (userTurns.length >= 4) {
|
|
95
|
+
const avgRecent = userTurns.slice(0, -1).reduce((s, t) => s + capWc(t.wordCount), 0) / (userTurns.length - 1);
|
|
96
|
+
if (wc < avgRecent * 0.4 && wc < 15 && !isFollowUp && !isOperationalFollowUp && !isFileReference) {
|
|
97
|
+
concerns.push({
|
|
98
|
+
severity: "warning",
|
|
99
|
+
category: "prompt-degradation",
|
|
100
|
+
message: `Your prompts are getting shorter (transcript avg ${Math.round(avgRecent)} words → ${wc} now). Quality may be degrading.`,
|
|
101
|
+
suggestion: "Take a moment to formulate a complete, self-contained request. The AI performs better with clear context.",
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else if (recent.length >= 3) {
|
|
107
|
+
const avgRecentLength = recent.reduce((s, r) => s + capWc(r.wordCount), 0) / recent.length;
|
|
108
|
+
if (wc < avgRecentLength * 0.4 && wc < 15 && !isFollowUp && !isOperationalFollowUp && !isFileReference) {
|
|
109
|
+
concerns.push({
|
|
110
|
+
severity: "warning",
|
|
111
|
+
category: "prompt-degradation",
|
|
112
|
+
message: `Your prompts are getting shorter (avg ${Math.round(avgRecentLength)} words → ${wc} now). Quality may be degrading.`,
|
|
113
|
+
suggestion: "Take a moment to formulate a complete, self-contained request. The AI performs better with clear context.",
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// 5. Long session fatigue warning
|
|
118
|
+
const minutes = sessionDurationMinutes(state);
|
|
119
|
+
if (minutes > 60 && state.turnCount > 0 && state.turnCount % 10 === 0) {
|
|
120
|
+
concerns.push({
|
|
121
|
+
severity: "info",
|
|
122
|
+
category: "session-fatigue",
|
|
123
|
+
message: `Session running for ${Math.round(minutes)} minutes with ${state.turnCount} turns. Consider stepping back for a high-level review.`,
|
|
124
|
+
suggestion: "Open a new chat to review the overall changes made so far, or take a break to re-evaluate the approach.",
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
// 6. Rapid-fire prompts without review
|
|
128
|
+
if (recent.length >= 3) {
|
|
129
|
+
const lastThreeTimestamps = recent.slice(-3).map((r) => r.timestamp);
|
|
130
|
+
const gaps = [];
|
|
131
|
+
for (let i = 1; i < lastThreeTimestamps.length; i++) {
|
|
132
|
+
gaps.push(lastThreeTimestamps[i] - lastThreeTimestamps[i - 1]);
|
|
133
|
+
}
|
|
134
|
+
const avgGapSeconds = gaps.reduce((s, g) => s + g, 0) / gaps.length / 1000;
|
|
135
|
+
if (avgGapSeconds < 15) {
|
|
136
|
+
concerns.push({
|
|
137
|
+
severity: "warning",
|
|
138
|
+
category: "rapid-fire",
|
|
139
|
+
message: "Rapid-fire prompting detected — average gap between prompts is under 15 seconds",
|
|
140
|
+
suggestion: "Slow down. Are you reviewing the AI's responses before sending the next prompt? Quick iterations often lead to compounding errors.",
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
// 7. [Transcript-only] Repeated rephrasings — user struggling with the same request
|
|
145
|
+
if (ctx && ctx.userTurnCount >= 3) {
|
|
146
|
+
const lastUserTurns = recentUserTurns(ctx, 4);
|
|
147
|
+
if (lastUserTurns.length >= 3) {
|
|
148
|
+
const similarities = countSimilarPairs(lastUserTurns.map((t) => t.text.toLowerCase()));
|
|
149
|
+
if (similarities >= 2) {
|
|
150
|
+
concerns.push({
|
|
151
|
+
severity: "info",
|
|
152
|
+
category: "repeated-rephrase",
|
|
153
|
+
message: "You appear to be rephrasing the same request multiple times. The AI may not understand what you need.",
|
|
154
|
+
suggestion: "Try a different approach: break the task into smaller steps, provide a concrete example of expected output, or reference specific code.",
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// 8. [Transcript-only] Context drift — current prompt is unrelated to the
|
|
160
|
+
// ongoing conversation thread without explicit topic change
|
|
161
|
+
if (ctx && ctx.userTurnCount >= 2 && wc > 10) {
|
|
162
|
+
const lastUser = ctx.lastUserText;
|
|
163
|
+
const lastAssistant = ctx.lastAssistantText;
|
|
164
|
+
if (lastUser && lastAssistant) {
|
|
165
|
+
const combined = (lastUser + " " + lastAssistant).toLowerCase();
|
|
166
|
+
const currentWords = new Set(words.map((w) => w.toLowerCase()).filter((w) => w.length > 4));
|
|
167
|
+
const overlapCount = [...currentWords].filter((w) => combined.includes(w)).length;
|
|
168
|
+
const overlapRatio = currentWords.size > 0 ? overlapCount / currentWords.size : 1;
|
|
169
|
+
if (overlapRatio < 0.1 && currentWords.size > 8) {
|
|
170
|
+
// Before flagging, check overlap with the session's first user prompt.
|
|
171
|
+
// In checklist-style sessions the user works through numbered items —
|
|
172
|
+
// each item has different vocabulary but relates to the opening plan.
|
|
173
|
+
const firstUserTurn = recentUserTurns(ctx, ctx.userTurnCount)[0];
|
|
174
|
+
let relatedToSessionPlan = false;
|
|
175
|
+
if (firstUserTurn && firstUserTurn !== ctx.turns.find(t => t.text === lastUser)) {
|
|
176
|
+
const planWords = firstUserTurn.text.toLowerCase();
|
|
177
|
+
const planOverlap = [...currentWords].filter((w) => planWords.includes(w)).length;
|
|
178
|
+
const planRatio = planOverlap / currentWords.size;
|
|
179
|
+
if (planRatio >= 0.15)
|
|
180
|
+
relatedToSessionPlan = true;
|
|
181
|
+
}
|
|
182
|
+
if (!relatedToSessionPlan) {
|
|
183
|
+
concerns.push({
|
|
184
|
+
severity: "info",
|
|
185
|
+
category: "context-drift",
|
|
186
|
+
message: "This prompt appears unrelated to the current conversation thread",
|
|
187
|
+
suggestion: "Consider starting a new chat for unrelated topics. Mixing contexts in a single session can confuse the AI and lead to errors.",
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// Block on warning+ severity so the user actually sees Hegel's feedback.
|
|
194
|
+
// Cursor only surfaces beforeSubmitPrompt's user_message when continue=false.
|
|
195
|
+
const shouldBlock = concerns.some((c) => c.severity === "critical" || c.severity === "warning");
|
|
196
|
+
return { concerns, shouldBlock };
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Counts how many adjacent pairs of strings share significant word overlap,
|
|
200
|
+
* indicating the user is rephrasing the same request.
|
|
201
|
+
*/
|
|
202
|
+
function countSimilarPairs(texts) {
|
|
203
|
+
let count = 0;
|
|
204
|
+
for (let i = 1; i < texts.length; i++) {
|
|
205
|
+
const prev = new Set(texts[i - 1].split(/\s+/).filter((w) => w.length > 3));
|
|
206
|
+
const curr = new Set(texts[i].split(/\s+/).filter((w) => w.length > 3));
|
|
207
|
+
if (prev.size === 0 || curr.size === 0)
|
|
208
|
+
continue;
|
|
209
|
+
const overlap = [...curr].filter((w) => prev.has(w)).length;
|
|
210
|
+
const ratio = overlap / Math.min(prev.size, curr.size);
|
|
211
|
+
if (ratio > 0.5)
|
|
212
|
+
count++;
|
|
213
|
+
}
|
|
214
|
+
return count;
|
|
215
|
+
}
|
|
216
|
+
export function buildPromptRecord(prompt, concerns) {
|
|
217
|
+
return {
|
|
218
|
+
timestamp: Date.now(),
|
|
219
|
+
prompt,
|
|
220
|
+
wordCount: prompt.trim().split(/\s+/).length,
|
|
221
|
+
concerns,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
//# sourceMappingURL=prompt-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-analyzer.js","sourceRoot":"","sources":["../../src/analyzers/prompt-analyzer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,2BAA2B,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEtG,4BAA4B;AAE5B,MAAM,aAAa,GAA8C;IAC/D,EAAE,OAAO,EAAE,6DAA6D,EAAE,KAAK,EAAE,2BAA2B,EAAE;IAC9G,EAAE,OAAO,EAAE,2DAA2D,EAAE,KAAK,EAAE,0CAA0C,EAAE;IAC3H,EAAE,OAAO,EAAE,6BAA6B,EAAE,KAAK,EAAE,uCAAuC,EAAE;IAC1F,EAAE,OAAO,EAAE,oCAAoC,EAAE,KAAK,EAAE,sDAAsD,EAAE;CACjH,CAAC;AAEF,MAAM,uBAAuB,GAAG;IAC9B,EAAE,IAAI,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,sEAAsE,EAAE;IAC3I,EAAE,IAAI,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,iCAAiC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,OAAO,EAAE,oFAAoF,EAAE;CAC/L,CAAC;AAEF,MAAM,yBAAyB,GAAG;IAChC,mEAAmE;CACpE,CAAC;AAEF,MAAM,YAAY,GAAG;IACnB,0EAA0E;IAC1E,kCAAkC;IAClC,KAAK,EAAG,wCAAwC;CACjD,CAAC;AAEF,MAAM,qBAAqB,GAAG,+IAA+I,CAAC;AAE9K,iBAAiB;AAEjB,MAAM,UAAU,aAAa,CAC3B,MAAc,EACd,KAAmB,EACnB,UAAqC;IAErC,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC;IACxB,MAAM,GAAG,GAAG,UAAU,IAAI,IAAI,CAAC;IAE/B,qEAAqE;IACrE,sEAAsE;IACtE,2DAA2D;IAC3D,MAAM,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,oBAAoB,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACnE,MAAM,mBAAmB,GAAG,GAAG,CAAC,CAAC,CAAC,2BAA2B,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC3E,MAAM,qBAAqB,GAAG,qBAAqB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjE,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE9E,iCAAiC;IACjC,4EAA4E;IAC5E,oEAAoE;IACpE,KAAK,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,aAAa,EAAE,CAAC;QAC/C,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC;YAChC,IAAI,UAAU,IAAI,mBAAmB,EAAE,CAAC;gBACtC,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,MAAM;oBAChB,QAAQ,EAAE,gBAAgB;oBAC1B,OAAO,EAAE,qBAAqB,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,2CAA2C;iBACpG,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,SAAS;oBACnB,QAAQ,EAAE,gBAAgB;oBAC1B,OAAO,EAAE,yBAAyB,KAAK,EAAE;oBACzC,UAAU,EAAE,6HAA6H;iBAC1I,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,6BAA6B;IAC7B,uEAAuE;IACvE,8EAA8E;IAC9E,KAAK,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,uBAAuB,EAAE,CAAC;QACxD,IAAI,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACjB,IAAI,UAAU;gBAAE,SAAS;YACzB,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,MAAM;gBAChB,QAAQ,EAAE,gBAAgB;gBAC1B,OAAO;gBACP,UAAU,EAAE,2FAA2F;aACxG,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,kDAAkD;IAClD,MAAM,iBAAiB,GAAG,yBAAyB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAChF,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7D,IAAI,iBAAiB,IAAI,CAAC,WAAW,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;QAChD,QAAQ,CAAC,IAAI,CAAC;YACZ,QAAQ,EAAE,MAAM;YAChB,QAAQ,EAAE,kBAAkB;YAC5B,OAAO,EAAE,0CAA0C;YACnD,UAAU,EAAE,6FAA6F;SAC1G,CAAC,CAAC;IACL,CAAC;IAED,iDAAiD;IACjD,6EAA6E;IAC7E,uEAAuE;IACvE,2CAA2C;IAC3C,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAEvC,yEAAyE;IACzE,uEAAuE;IACvE,MAAM,KAAK,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAEtD,IAAI,GAAG,IAAI,GAAG,CAAC,aAAa,IAAI,CAAC,EAAE,CAAC;QAClC,MAAM,SAAS,GAAG,eAAe,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC1C,IAAI,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YAC1B,MAAM,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC9G,IAAI,EAAE,GAAG,SAAS,GAAG,GAAG,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC,qBAAqB,IAAI,CAAC,eAAe,EAAE,CAAC;gBACjG,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,SAAS;oBACnB,QAAQ,EAAE,oBAAoB;oBAC9B,OAAO,EAAE,oDAAoD,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,YAAY,EAAE,kCAAkC;oBAClI,UAAU,EAAE,2GAA2G;iBACxH,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;SAAM,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QAC9B,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC;QAC3F,IAAI,EAAE,GAAG,eAAe,GAAG,GAAG,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC,qBAAqB,IAAI,CAAC,eAAe,EAAE,CAAC;YACvG,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,SAAS;gBACnB,QAAQ,EAAE,oBAAoB;gBAC9B,OAAO,EAAE,yCAAyC,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,YAAY,EAAE,kCAAkC;gBAC7H,UAAU,EAAE,2GAA2G;aACxH,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,kCAAkC;IAClC,MAAM,OAAO,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;IAC9C,IAAI,OAAO,GAAG,EAAE,IAAI,KAAK,CAAC,SAAS,GAAG,CAAC,IAAI,KAAK,CAAC,SAAS,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC;QACtE,QAAQ,CAAC,IAAI,CAAC;YACZ,QAAQ,EAAE,MAAM;YAChB,QAAQ,EAAE,iBAAiB;YAC3B,OAAO,EAAE,uBAAuB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,iBAAiB,KAAK,CAAC,SAAS,yDAAyD;YAC5I,UAAU,EAAE,yGAAyG;SACtH,CAAC,CAAC;IACL,CAAC;IAED,uCAAuC;IACvC,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;QACvB,MAAM,mBAAmB,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACrE,MAAM,IAAI,GAAG,EAAE,CAAC;QAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,mBAAmB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACpD,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACjE,CAAC;QACD,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAC3E,IAAI,aAAa,GAAG,EAAE,EAAE,CAAC;YACvB,QAAQ,CAAC,IAAI,CAAC;gBACZ,QAAQ,EAAE,SAAS;gBACnB,QAAQ,EAAE,YAAY;gBACtB,OAAO,EAAE,iFAAiF;gBAC1F,UAAU,EAAE,oIAAoI;aACjJ,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,oFAAoF;IACpF,IAAI,GAAG,IAAI,GAAG,CAAC,aAAa,IAAI,CAAC,EAAE,CAAC;QAClC,MAAM,aAAa,GAAG,eAAe,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QAC9C,IAAI,aAAa,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YAC9B,MAAM,YAAY,GAAG,iBAAiB,CACpC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAC/C,CAAC;YACF,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;gBACtB,QAAQ,CAAC,IAAI,CAAC;oBACZ,QAAQ,EAAE,MAAM;oBAChB,QAAQ,EAAE,mBAAmB;oBAC7B,OAAO,EAAE,uGAAuG;oBAChH,UAAU,EAAE,yIAAyI;iBACtJ,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,+DAA+D;IAC/D,IAAI,GAAG,IAAI,GAAG,CAAC,aAAa,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC;QAC7C,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,CAAC;QAClC,MAAM,aAAa,GAAG,GAAG,CAAC,iBAAiB,CAAC;QAC5C,IAAI,QAAQ,IAAI,aAAa,EAAE,CAAC;YAC9B,MAAM,QAAQ,GAAG,CAAC,QAAQ,GAAG,GAAG,GAAG,aAAa,CAAC,CAAC,WAAW,EAAE,CAAC;YAChE,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;YAC5F,MAAM,YAAY,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;YAClF,MAAM,YAAY,GAAG,YAAY,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YAElF,IAAI,YAAY,GAAG,GAAG,IAAI,YAAY,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;gBAChD,uEAAuE;gBACvE,sEAAsE;gBACtE,sEAAsE;gBACtE,MAAM,aAAa,GAAG,eAAe,CAAC,GAAG,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;gBACjE,IAAI,oBAAoB,GAAG,KAAK,CAAC;gBACjC,IAAI,aAAa,IAAI,aAAa,KAAK,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,EAAE,CAAC;oBAChF,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;oBACnD,MAAM,WAAW,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;oBAClF,MAAM,SAAS,GAAG,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC;oBAClD,IAAI,SAAS,IAAI,IAAI;wBAAE,oBAAoB,GAAG,IAAI,CAAC;gBACrD,CAAC;gBAED,IAAI,CAAC,oBAAoB,EAAE,CAAC;oBAC1B,QAAQ,CAAC,IAAI,CAAC;wBACZ,QAAQ,EAAE,MAAM;wBAChB,QAAQ,EAAE,eAAe;wBACzB,OAAO,EAAE,kEAAkE;wBAC3E,UAAU,EAAE,+HAA+H;qBAC5I,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,8EAA8E;IAC9E,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,CAC/B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,CAC7D,CAAC;IAEF,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,SAAS,iBAAiB,CAAC,KAAe;IACxC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5E,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;QACxE,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;YAAE,SAAS;QACjD,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;QAC5D,MAAM,KAAK,GAAG,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACvD,IAAI,KAAK,GAAG,GAAG;YAAE,KAAK,EAAE,CAAC;IAC3B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,QAAmB;IAEnB,OAAO;QACL,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;QACrB,MAAM;QACN,SAAS,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM;QAC5C,QAAQ;KACT,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Concern, SessionState, ResponseRecord, TranscriptContext } from "../types.js";
|
|
2
|
+
export declare function analyzeResponse(text: string, state: SessionState, transcript?: TranscriptContext | null): {
|
|
3
|
+
concerns: Concern[];
|
|
4
|
+
};
|
|
5
|
+
export declare function buildResponseRecord(text: string, concerns: Concern[], unprompted?: boolean): ResponseRecord;
|
|
6
|
+
//# sourceMappingURL=response-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/response-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AA6C5F,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,YAAY,EACnB,UAAU,CAAC,EAAE,iBAAiB,GAAG,IAAI,GACpC;IAAE,QAAQ,EAAE,OAAO,EAAE,CAAA;CAAE,CA6IzB;AAyDD,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,EAAE,EACnB,UAAU,UAAQ,GACjB,cAAc,CAOhB"}
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import { totalFilesEdited, totalLinesChanged } from "../state.js";
|
|
2
|
+
import { recentAssistantTurns, recentUserTurns } from "../transcript.js";
|
|
3
|
+
// ── Pattern Definitions ──
|
|
4
|
+
const OVERCONFIDENCE_PATTERNS = [
|
|
5
|
+
{
|
|
6
|
+
pattern: /\b(this is the (only )?correct|this will definitely|guaranteed to work)\b/i,
|
|
7
|
+
message: "Overconfident language — AI is claiming certainty without caveats",
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
pattern: /\b(I've fixed all|all issues are resolved|everything.+works now|completely fixed)\b/i,
|
|
11
|
+
message: "Blanket 'everything fixed' claim — did you verify all edge cases?",
|
|
12
|
+
},
|
|
13
|
+
];
|
|
14
|
+
const SYCOPHANCY_PATTERNS = [
|
|
15
|
+
{
|
|
16
|
+
pattern: /\b(you'?re (absolutely |completely )?right|I (completely |fully )?agree with your (approach|assessment|analysis))\b/i,
|
|
17
|
+
message: "Sycophantic agreement detected — is the AI genuinely agreeing or just being agreeable?",
|
|
18
|
+
},
|
|
19
|
+
];
|
|
20
|
+
const MISSING_VERIFICATION = [
|
|
21
|
+
{
|
|
22
|
+
trigger: /\b(refactor|restructur|rewrit|migrat|redesign|overhaul)\b/i,
|
|
23
|
+
check: /\b(test|verify|check|ensure|validate|confirm|run)\b/i,
|
|
24
|
+
message: "Major structural change proposed without explicit verification step",
|
|
25
|
+
suggestion: "Ask: 'How can we verify this refactoring didn't break anything?' before accepting.",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
trigger: /\b(security|auth|access control|credential|secret|token|password|encrypt)\b/i,
|
|
29
|
+
check: /\b(review|audit|test|verify|vulnerabilit)\b/i,
|
|
30
|
+
message: "Security-related change without security review mention",
|
|
31
|
+
suggestion: "Security changes deserve explicit review. Consider asking for a threat model or security-specific test cases.",
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
const SCOPE_CREEP_THRESHOLD = 8;
|
|
35
|
+
const LINES_CHANGED_THRESHOLD = 200;
|
|
36
|
+
const INTENTIONAL_BROAD_SCOPE_PATTERN = /\b(audit|refactor|fix(es)?|review|update|align|migrate|rename|across|all files|codebase|inconsistenc|cover|coverage|extend|next step|follow-?up|integration-style|also|proceed with|now do)\b/i;
|
|
37
|
+
// ── Analyzer ──
|
|
38
|
+
export function analyzeResponse(text, state, transcript) {
|
|
39
|
+
const concerns = [];
|
|
40
|
+
const ctx = transcript ?? null;
|
|
41
|
+
// 1. Overconfidence detection
|
|
42
|
+
for (const { pattern, message } of OVERCONFIDENCE_PATTERNS) {
|
|
43
|
+
if (pattern.test(text)) {
|
|
44
|
+
concerns.push({
|
|
45
|
+
severity: "warning",
|
|
46
|
+
category: "overconfidence",
|
|
47
|
+
message,
|
|
48
|
+
suggestion: "Ask the AI: 'What could go wrong with this approach?' or 'What edge cases might this miss?'",
|
|
49
|
+
});
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// 2. Sycophancy detection
|
|
54
|
+
for (const { pattern, message } of SYCOPHANCY_PATTERNS) {
|
|
55
|
+
if (pattern.test(text)) {
|
|
56
|
+
concerns.push({
|
|
57
|
+
severity: "info",
|
|
58
|
+
category: "sycophancy",
|
|
59
|
+
message,
|
|
60
|
+
suggestion: "If the AI immediately agrees with everything, try playing devil's advocate: 'What arguments exist against this approach?'",
|
|
61
|
+
});
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// 3. Missing verification for risky changes
|
|
66
|
+
const hasCodeChanges = totalFilesEdited(state) > 0 || totalLinesChanged(state) > 0;
|
|
67
|
+
if (hasCodeChanges) {
|
|
68
|
+
for (const { trigger, check, message, suggestion } of MISSING_VERIFICATION) {
|
|
69
|
+
if (trigger.test(text) && !check.test(text)) {
|
|
70
|
+
concerns.push({
|
|
71
|
+
severity: "warning",
|
|
72
|
+
category: "missing-verification",
|
|
73
|
+
message,
|
|
74
|
+
suggestion,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
// 4. Scope creep: too many files touched in the session
|
|
80
|
+
// Suppress when the session's opening prompt explicitly describes
|
|
81
|
+
// multi-file work (audit, refactor, fix list, etc.)
|
|
82
|
+
const filesEdited = totalFilesEdited(state);
|
|
83
|
+
if (filesEdited > SCOPE_CREEP_THRESHOLD && state.turnCount > 3) {
|
|
84
|
+
const alreadyWarned = state.concerns.some((c) => c.category === "scope-creep");
|
|
85
|
+
let intentionalBroadScope = false;
|
|
86
|
+
if (ctx) {
|
|
87
|
+
const userTurns = recentUserTurns(ctx, ctx.userTurnCount);
|
|
88
|
+
const firstUser = userTurns[0];
|
|
89
|
+
const recentUsers = userTurns.slice(-3);
|
|
90
|
+
intentionalBroadScope = [firstUser, ...recentUsers]
|
|
91
|
+
.filter((turn) => !!turn)
|
|
92
|
+
.some((turn) => INTENTIONAL_BROAD_SCOPE_PATTERN.test(turn.text));
|
|
93
|
+
}
|
|
94
|
+
else if (state.prompts.length > 0) {
|
|
95
|
+
intentionalBroadScope = [state.prompts[0], ...state.prompts.slice(-3)]
|
|
96
|
+
.some((prompt) => INTENTIONAL_BROAD_SCOPE_PATTERN.test(prompt.prompt));
|
|
97
|
+
}
|
|
98
|
+
if (!alreadyWarned && !intentionalBroadScope) {
|
|
99
|
+
concerns.push({
|
|
100
|
+
severity: "warning",
|
|
101
|
+
category: "scope-creep",
|
|
102
|
+
message: `${filesEdited} files modified this session. The scope may be expanding beyond the original intent.`,
|
|
103
|
+
suggestion: "Pause and ask: 'Is this still aligned with what I originally set out to do?' Consider committing what you have and starting a focused follow-up.",
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// 5. Large volume of changes without tests
|
|
108
|
+
const lines = totalLinesChanged(state);
|
|
109
|
+
if (lines > LINES_CHANGED_THRESHOLD) {
|
|
110
|
+
const alreadyWarned = state.concerns.some((c) => c.category === "untested-changes");
|
|
111
|
+
const hasTestActivity = ctx ?
|
|
112
|
+
recentUserTurns(ctx, 3).some(t => t && /\b(test|spec|jest|vitest|mocha|cypress|playwright)\b/i.test(t.text)) :
|
|
113
|
+
state.prompts.slice(-3).some(p => /\b(test|spec|jest|vitest|mocha|cypress|playwright)\b/i.test(p.prompt));
|
|
114
|
+
if (!alreadyWarned && !hasTestActivity) {
|
|
115
|
+
concerns.push({
|
|
116
|
+
severity: "warning",
|
|
117
|
+
category: "untested-changes",
|
|
118
|
+
message: `${lines} lines changed so far without any test-related activity detected`,
|
|
119
|
+
suggestion: "Consider asking the AI to generate tests for the changes, or run existing tests before continuing.",
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// 6. [Transcript-only] Self-contradiction — the AI reverses a position
|
|
124
|
+
// it stated in a recent response without acknowledging the change.
|
|
125
|
+
if (ctx && ctx.assistantTurnCount >= 2) {
|
|
126
|
+
const recentResponses = recentAssistantTurns(ctx, 3);
|
|
127
|
+
const contradiction = detectContradiction(text, recentResponses.map((t) => t.text));
|
|
128
|
+
if (contradiction) {
|
|
129
|
+
concerns.push({
|
|
130
|
+
severity: "warning",
|
|
131
|
+
category: "self-contradiction",
|
|
132
|
+
message: contradiction,
|
|
133
|
+
suggestion: "Ask the AI: 'You previously said X but now say Y — what changed?' Contradictions may indicate the AI is guessing rather than reasoning.",
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// 7. [Transcript-only] Non-responsive — the response doesn't address the
|
|
138
|
+
// user's last request (keyword overlap check).
|
|
139
|
+
// For multi-topic prompts (bullet points, line breaks), check each
|
|
140
|
+
// segment individually — the response may focus on one sub-topic.
|
|
141
|
+
if (ctx && ctx.lastUserText) {
|
|
142
|
+
const responseWords = significantWords(text);
|
|
143
|
+
const segments = ctx.lastUserText.split(/\n[-•*]\s*|\n{2,}/).filter(s => s.trim().length > 10);
|
|
144
|
+
const segmentSets = segments.length > 1
|
|
145
|
+
? segments.map(s => significantWords(s))
|
|
146
|
+
: [significantWords(ctx.lastUserText)];
|
|
147
|
+
const bestRatio = Math.max(...segmentSets.map(userWords => {
|
|
148
|
+
if (userWords.size < 5)
|
|
149
|
+
return 1;
|
|
150
|
+
const overlap = [...userWords].filter(w => responseWords.has(w)).length;
|
|
151
|
+
return overlap / userWords.size;
|
|
152
|
+
}));
|
|
153
|
+
if (bestRatio < 0.05 && text.length > 200) {
|
|
154
|
+
concerns.push({
|
|
155
|
+
severity: "info",
|
|
156
|
+
category: "non-responsive",
|
|
157
|
+
message: "The AI's response has very low overlap with your request — it may be addressing something different",
|
|
158
|
+
suggestion: "Compare the response to your original question. If it's off-topic, re-state your request clearly.",
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return { concerns };
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Checks for simple contradictions between the current response and recent ones.
|
|
166
|
+
* Looks for explicit negation of previously stated positions.
|
|
167
|
+
*/
|
|
168
|
+
function detectContradiction(current, previousResponses) {
|
|
169
|
+
const CONTRADICTION_PAIRS = [
|
|
170
|
+
[
|
|
171
|
+
/\b(you should|I recommend|the (best|right) (approach|way))\b.*\b(not|don't|avoid|instead of)\b.*\b(\w{4,})\b/i,
|
|
172
|
+
/\b(you should|I recommend|the (best|right) (approach|way))\b.*\b(\w{4,})\b/i,
|
|
173
|
+
"AI may have reversed its recommendation",
|
|
174
|
+
],
|
|
175
|
+
[
|
|
176
|
+
/\b(this (is|was) (not |un)?necessary)\b/i,
|
|
177
|
+
/\b(this (is|was) (not |un)?necessary)\b/i,
|
|
178
|
+
"AI's assessment of necessity may have flipped",
|
|
179
|
+
],
|
|
180
|
+
];
|
|
181
|
+
for (const prev of previousResponses) {
|
|
182
|
+
for (const [currentPattern, prevPattern, message] of CONTRADICTION_PAIRS) {
|
|
183
|
+
if (currentPattern.test(current) && prevPattern.test(prev)) {
|
|
184
|
+
const currentNegated = /\b(not|don't|shouldn't|avoid|never)\b/i.test(current);
|
|
185
|
+
const prevNegated = /\b(not|don't|shouldn't|avoid|never)\b/i.test(prev);
|
|
186
|
+
if (currentNegated !== prevNegated) {
|
|
187
|
+
return message;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
function significantWords(text) {
|
|
195
|
+
const STOP_WORDS = new Set([
|
|
196
|
+
"the", "a", "an", "is", "are", "was", "were", "be", "been", "being",
|
|
197
|
+
"have", "has", "had", "do", "does", "did", "will", "would", "could",
|
|
198
|
+
"should", "may", "might", "shall", "can", "need", "must", "that",
|
|
199
|
+
"this", "these", "those", "with", "from", "into", "for", "and",
|
|
200
|
+
"but", "not", "you", "your", "it", "its", "they", "them", "their",
|
|
201
|
+
"what", "which", "who", "when", "where", "how", "all", "each",
|
|
202
|
+
"every", "both", "few", "more", "most", "other", "some", "such",
|
|
203
|
+
"than", "too", "very", "just", "also", "here", "there", "then",
|
|
204
|
+
"now", "only", "about", "after", "before", "between", "over",
|
|
205
|
+
]);
|
|
206
|
+
return new Set(text.toLowerCase()
|
|
207
|
+
.split(/\s+/)
|
|
208
|
+
.filter((w) => w.length > 3 && !STOP_WORDS.has(w)));
|
|
209
|
+
}
|
|
210
|
+
export function buildResponseRecord(text, concerns, unprompted = false) {
|
|
211
|
+
return {
|
|
212
|
+
timestamp: Date.now(),
|
|
213
|
+
textLength: text.length,
|
|
214
|
+
concerns,
|
|
215
|
+
...(unprompted && { unprompted }),
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=response-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"response-analyzer.js","sourceRoot":"","sources":["../../src/analyzers/response-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Concern, SessionState, TranscriptContext } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Produces a human-readable session summary with accumulated concerns.
|
|
4
|
+
* Called at the stop hook — this is Hegel's "end of turn" dialectical review.
|
|
5
|
+
*/
|
|
6
|
+
export declare function analyzeSession(state: SessionState, transcript?: TranscriptContext | null): {
|
|
7
|
+
summary: string;
|
|
8
|
+
concerns: Concern[];
|
|
9
|
+
};
|
|
10
|
+
//# sourceMappingURL=session-analyzer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-analyzer.d.ts","sourceRoot":"","sources":["../../src/analyzers/session-analyzer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AA4D5E;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,YAAY,EACnB,UAAU,CAAC,EAAE,iBAAiB,GAAG,IAAI,GACpC;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,OAAO,EAAE,CAAC;CACrB,CAqLA"}
|