promptvet-core 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 +278 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +273 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/layers/heuristics/actionVerbs.d.ts +4 -0
- package/dist/layers/heuristics/actionVerbs.d.ts.map +1 -0
- package/dist/layers/heuristics/actionVerbs.js +9 -0
- package/dist/layers/heuristics/actionVerbs.js.map +1 -0
- package/dist/layers/heuristics/browserApiRisk.d.ts +2 -0
- package/dist/layers/heuristics/browserApiRisk.d.ts.map +1 -0
- package/dist/layers/heuristics/browserApiRisk.js +18 -0
- package/dist/layers/heuristics/browserApiRisk.js.map +1 -0
- package/dist/layers/heuristics/frustrationSignal.d.ts +2 -0
- package/dist/layers/heuristics/frustrationSignal.d.ts.map +1 -0
- package/dist/layers/heuristics/frustrationSignal.js +26 -0
- package/dist/layers/heuristics/frustrationSignal.js.map +1 -0
- package/dist/layers/heuristics/geoFlakeRisk.d.ts +2 -0
- package/dist/layers/heuristics/geoFlakeRisk.d.ts.map +1 -0
- package/dist/layers/heuristics/geoFlakeRisk.js +14 -0
- package/dist/layers/heuristics/geoFlakeRisk.js.map +1 -0
- package/dist/layers/heuristics/missingFramework.d.ts +2 -0
- package/dist/layers/heuristics/missingFramework.d.ts.map +1 -0
- package/dist/layers/heuristics/missingFramework.js +16 -0
- package/dist/layers/heuristics/missingFramework.js.map +1 -0
- package/dist/layers/heuristics/missingMockStrategy.d.ts +2 -0
- package/dist/layers/heuristics/missingMockStrategy.d.ts.map +1 -0
- package/dist/layers/heuristics/missingMockStrategy.js +17 -0
- package/dist/layers/heuristics/missingMockStrategy.js.map +1 -0
- package/dist/layers/heuristics/missingOutputFormat.d.ts +2 -0
- package/dist/layers/heuristics/missingOutputFormat.d.ts.map +1 -0
- package/dist/layers/heuristics/missingOutputFormat.js +31 -0
- package/dist/layers/heuristics/missingOutputFormat.js.map +1 -0
- package/dist/layers/heuristics/missingScope.d.ts +2 -0
- package/dist/layers/heuristics/missingScope.d.ts.map +1 -0
- package/dist/layers/heuristics/missingScope.js +11 -0
- package/dist/layers/heuristics/missingScope.js.map +1 -0
- package/dist/layers/heuristics/noActionableIntent.d.ts +2 -0
- package/dist/layers/heuristics/noActionableIntent.d.ts.map +1 -0
- package/dist/layers/heuristics/noActionableIntent.js +14 -0
- package/dist/layers/heuristics/noActionableIntent.js.map +1 -0
- package/dist/layers/linguistic/bloatDetector.d.ts +2 -0
- package/dist/layers/linguistic/bloatDetector.d.ts.map +1 -0
- package/dist/layers/linguistic/bloatDetector.js +91 -0
- package/dist/layers/linguistic/bloatDetector.js.map +1 -0
- package/dist/layers/linguistic/chainedIntent.d.ts +3 -0
- package/dist/layers/linguistic/chainedIntent.d.ts.map +1 -0
- package/dist/layers/linguistic/chainedIntent.js +26 -0
- package/dist/layers/linguistic/chainedIntent.js.map +1 -0
- package/dist/layers/linguistic/hedgeDetector.d.ts +2 -0
- package/dist/layers/linguistic/hedgeDetector.d.ts.map +1 -0
- package/dist/layers/linguistic/hedgeDetector.js +12 -0
- package/dist/layers/linguistic/hedgeDetector.js.map +1 -0
- package/dist/layers/linguistic/negationDensity.d.ts +2 -0
- package/dist/layers/linguistic/negationDensity.d.ts.map +1 -0
- package/dist/layers/linguistic/negationDensity.js +8 -0
- package/dist/layers/linguistic/negationDensity.js.map +1 -0
- package/dist/layers/linguistic/passiveVoice.d.ts +2 -0
- package/dist/layers/linguistic/passiveVoice.d.ts.map +1 -0
- package/dist/layers/linguistic/passiveVoice.js +8 -0
- package/dist/layers/linguistic/passiveVoice.js.map +1 -0
- package/dist/layers/linguistic/pronounAmbiguity.d.ts +2 -0
- package/dist/layers/linguistic/pronounAmbiguity.d.ts.map +1 -0
- package/dist/layers/linguistic/pronounAmbiguity.js +25 -0
- package/dist/layers/linguistic/pronounAmbiguity.js.map +1 -0
- package/dist/layers/linguistic/tokenCount.d.ts +2 -0
- package/dist/layers/linguistic/tokenCount.d.ts.map +1 -0
- package/dist/layers/linguistic/tokenCount.js +6 -0
- package/dist/layers/linguistic/tokenCount.js.map +1 -0
- package/dist/layers/semantic/classifier.d.ts +7 -0
- package/dist/layers/semantic/classifier.d.ts.map +1 -0
- package/dist/layers/semantic/classifier.js +40 -0
- package/dist/layers/semantic/classifier.js.map +1 -0
- package/dist/layers/syscan/auditor.d.ts +12 -0
- package/dist/layers/syscan/auditor.d.ts.map +1 -0
- package/dist/layers/syscan/auditor.js +108 -0
- package/dist/layers/syscan/auditor.js.map +1 -0
- package/dist/layers/syscan/qePersona.d.ts +2 -0
- package/dist/layers/syscan/qePersona.d.ts.map +1 -0
- package/dist/layers/syscan/qePersona.js +45 -0
- package/dist/layers/syscan/qePersona.js.map +1 -0
- package/dist/scorer/fixSuggestions.d.ts +2 -0
- package/dist/scorer/fixSuggestions.d.ts.map +1 -0
- package/dist/scorer/fixSuggestions.js +18 -0
- package/dist/scorer/fixSuggestions.js.map +1 -0
- package/dist/scorer/scorer.d.ts +23 -0
- package/dist/scorer/scorer.d.ts.map +1 -0
- package/dist/scorer/scorer.js +122 -0
- package/dist/scorer/scorer.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { getLlama, LlamaChatSession, resolveModelFile } from 'node-llama-cpp';
|
|
2
|
+
import { QE_PERSONA } from './qePersona.js';
|
|
3
|
+
export const DEFAULT_MODEL = 'hf:ggml-org/SmolLM3-3B-GGUF:Q4_K_M';
|
|
4
|
+
let llamaInstance = null;
|
|
5
|
+
let modelInstance = null;
|
|
6
|
+
let loadedModelUri = null;
|
|
7
|
+
async function resolveModelPath(modelUri) {
|
|
8
|
+
if (!modelUri.startsWith('hf:')) {
|
|
9
|
+
return modelUri;
|
|
10
|
+
}
|
|
11
|
+
let didDownload = false;
|
|
12
|
+
const modelPath = await resolveModelFile(modelUri, {
|
|
13
|
+
onProgress({ downloadedSize, totalSize }) {
|
|
14
|
+
if (!didDownload) {
|
|
15
|
+
didDownload = true;
|
|
16
|
+
process.stderr.write('Downloading model — this only happens once...\n');
|
|
17
|
+
}
|
|
18
|
+
const pct = totalSize > 0 ? Math.round((downloadedSize / totalSize) * 100) : 0;
|
|
19
|
+
process.stderr.write(`\r ${pct}%`);
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
if (didDownload) {
|
|
23
|
+
process.stderr.write('\n Download complete.\n');
|
|
24
|
+
}
|
|
25
|
+
return modelPath;
|
|
26
|
+
}
|
|
27
|
+
async function getModel(modelUri) {
|
|
28
|
+
if (modelInstance !== null && loadedModelUri === modelUri) {
|
|
29
|
+
return modelInstance;
|
|
30
|
+
}
|
|
31
|
+
if (llamaInstance === null) {
|
|
32
|
+
llamaInstance = await getLlama();
|
|
33
|
+
}
|
|
34
|
+
const modelPath = await resolveModelPath(modelUri);
|
|
35
|
+
process.stderr.write('Loading model...\n');
|
|
36
|
+
const model = await llamaInstance.loadModel({ modelPath });
|
|
37
|
+
modelInstance = model;
|
|
38
|
+
loadedModelUri = modelUri;
|
|
39
|
+
return model;
|
|
40
|
+
}
|
|
41
|
+
function wordOverlap(a, b) {
|
|
42
|
+
const wordsA = new Set(a.toLowerCase().split(/\W+/).filter(Boolean));
|
|
43
|
+
const wordsB = new Set(b.toLowerCase().split(/\W+/).filter(Boolean));
|
|
44
|
+
let intersection = 0;
|
|
45
|
+
for (const w of wordsA) {
|
|
46
|
+
if (wordsB.has(w))
|
|
47
|
+
intersection++;
|
|
48
|
+
}
|
|
49
|
+
const union = wordsA.size + wordsB.size - intersection;
|
|
50
|
+
return union === 0 ? 0 : intersection / union;
|
|
51
|
+
}
|
|
52
|
+
function parseGaps(raw) {
|
|
53
|
+
if (!raw || /no gaps (found|detected)/i.test(raw))
|
|
54
|
+
return [];
|
|
55
|
+
const parts = raw.split(/\bGAP:/i).slice(1);
|
|
56
|
+
const gaps = [];
|
|
57
|
+
for (const part of parts) {
|
|
58
|
+
const lines = part.split('\n').map(l => l.trim()).filter(Boolean);
|
|
59
|
+
const summary = lines[0] ?? '';
|
|
60
|
+
const whyLine = lines.find(l => /^WHY:/i.test(l));
|
|
61
|
+
const detail = whyLine ? whyLine.replace(/^WHY:\s*/i, '') : '';
|
|
62
|
+
if (summary) {
|
|
63
|
+
gaps.push({ summary, detail });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const deduped = [];
|
|
67
|
+
for (const gap of gaps) {
|
|
68
|
+
const isDuplicate = deduped.some(kept => wordOverlap(gap.summary, kept.summary) > 0.65);
|
|
69
|
+
if (!isDuplicate)
|
|
70
|
+
deduped.push(gap);
|
|
71
|
+
}
|
|
72
|
+
return deduped;
|
|
73
|
+
}
|
|
74
|
+
export async function auditSystemPrompt(prompt, modelUri = DEFAULT_MODEL) {
|
|
75
|
+
if (!prompt || prompt.trim() === '')
|
|
76
|
+
return { gaps: [], raw: '' };
|
|
77
|
+
if (prompt.trim().split(/\s+/).length < 3)
|
|
78
|
+
return { gaps: [], raw: '' };
|
|
79
|
+
const model = await getModel(modelUri);
|
|
80
|
+
const context = await model.createContext();
|
|
81
|
+
process.stderr.write('Running deep audit — this typically takes 30–60 seconds...\n');
|
|
82
|
+
const session = new LlamaChatSession({
|
|
83
|
+
contextSequence: context.getSequence(),
|
|
84
|
+
systemPrompt: QE_PERSONA,
|
|
85
|
+
});
|
|
86
|
+
const userMessage = `SPECIFICATION UNDER REVIEW:\n` +
|
|
87
|
+
`"""\n${prompt}\n"""\n\n` +
|
|
88
|
+
`TASK: Perform a static QE review of the specification above.\n\n` +
|
|
89
|
+
`WHAT IS NOT A GAP (skip these entirely):\n` +
|
|
90
|
+
`- Contextual descriptors about the user (age, experience level, fitness level, preferences, background). These define the user, they are not unhandled scenarios.\n` +
|
|
91
|
+
`- Behaviours the prompt already defines explicitly — if it's covered, skip it.\n` +
|
|
92
|
+
`- Subjective quality concerns (e.g. "could be more specific"). Only flag structural failures.\n` +
|
|
93
|
+
`- Anything that requires inventing a hypothetical user that the prompt clearly does not serve.\n\n` +
|
|
94
|
+
`WHAT IS A GENUINE GAP:\n` +
|
|
95
|
+
`- A realistic input scenario the prompt will encounter but provides NO handling for.\n` +
|
|
96
|
+
`- A negative constraint ("do not X") with no fallback — what does the AI do instead?\n` +
|
|
97
|
+
`- Two instructions that directly contradict each other.\n` +
|
|
98
|
+
`- A missing escalation path when out-of-scope or malicious input arrives.\n\n` +
|
|
99
|
+
`If no genuine gaps exist, output exactly: NO GAPS FOUND\n\n` +
|
|
100
|
+
`Otherwise use GAP:/WHY: format only. No preamble, no commentary.`;
|
|
101
|
+
const raw = await session.prompt(userMessage, {
|
|
102
|
+
maxTokens: 512,
|
|
103
|
+
temperature: 0,
|
|
104
|
+
});
|
|
105
|
+
const gaps = parseGaps(raw);
|
|
106
|
+
return { gaps, raw };
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=auditor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auditor.js","sourceRoot":"","sources":["../../../src/layers/syscan/auditor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const QE_PERSONA = "You are a Senior Quality Engineering analyst reviewing system prompt specifications. Your sole job is to find what is NOT covered \u2014 missing boundaries, unhandled edge cases, or negative constraint traps.\n\nRULES:\n- Do NOT adopt the persona of the system prompt.\n- Do NOT respond in JSON. For each gap, output exactly:\n GAP: [one-line summary]\n WHY: [one-line explanation]\n- Do NOT assume a broad instruction (e.g. \"only do X\") acts as a fallback for a forbidden action. If the spec tells the AI what NOT to do, it MUST define the exact conversational response or script it should say instead.\n- Only return 'No gaps found' if EVERY forbidden action has an explicit fallback script AND EVERY out-of-scope input has defined handling. If even one forbidden action lacks a fallback, flag it.\n- Do NOT flag in-scope user questions. If a user asks something that falls within the agent's defined role and domain, the agent handles it by design \u2014 that is NOT a gap. A fitness coach handles fitness questions. A SQL generator handles SQL requests. Only flag gaps where the prompt explicitly forbids something without defining a fallback, or where out-of-scope inputs have no defined handling.\n- Do NOT invent user scenarios that the prompt does not address. Only flag gaps that represent a realistic production failure \u2014 where the system would break, go silent, or produce harmful output.\n\nNOTE: The examples below show reasoning patterns. Apply the pattern, not the content \u2014 gaps must come from the specification under review, not from example topics.\n\n---\nFEW-SHOT TRAINING EXAMPLES\n---\nEXAMPLE 1 \u2014 Negative constraint trap (flag this):\nINPUT SPEC: \"You are a Python assistant. Write code functions. Never explain anything.\"\nGAP: Missing instructions for non-technical user questions or prompt injection attacks.\nWHY: The system forces the model to generate Python syntax even from raw text noise or malicious payloads, resulting in syntax errors or crashes in production.\n\nEXAMPLE 2 \u2014 Banned topic with no fallback script (flag this):\nINPUT SPEC: \"You are a travel assistant. Help users plan trips and itineraries. Never discuss visa requirements or immigration processes.\"\nGAP: Missing explicit conversational fallback when a traveller asks about visa requirements.\nWHY: The spec bans a high-demand topic but defines no response, leaving the agent silent at the exact moment a traveller needs guidance \u2014 breaking trust and potentially causing a missed booking.\n\nEXAMPLE 3 \u2014 In-scope questions are NOT gaps, but missing scope boundary IS (flag only the real gap):\nINPUT SPEC: \"You are an expert fitness coach. Design science-based workout programs. Use progressive overload. Deload every 4-6 weeks is mandatory.\"\nNOT A GAP: A user asking about deload rationale, kettlebell benefits, or exercise selection \u2014 these are in-scope fitness questions the coach handles by design.\nGAP: Missing handling for out-of-scope inputs such as nutrition advice, injury diagnosis, or supplement recommendations \u2014 the prompt defines no boundary or fallback for these domains.\nWHY: The spec defines a training role but sets no scope boundary, leaving the agent without a defined response when users push into adjacent domains it was not designed to cover.\n\nEXAMPLE 4 \u2014 Multiple forbidden actions, each needs its own fallback (flag all):\nINPUT SPEC: \"You are a customer service agent for an airline. Never discuss compensation claims. Never discuss flight delays. Only answer booking questions.\"\nGAP 1: No defined redirect when a customer raises a compensation claim.\nWHY: A legally sensitive topic is banned with no script, leaving the agent silent or improvising on a liability-bearing issue.\nGAP 2: Delayed-flight passengers have no handling path \u2014 a banned topic the spec leaves entirely undefined.\nWHY: Flight disruptions carry urgency and emotional load; an agent with no response for this scenario risks escalating customer frustration at the worst moment.\n---\n\nPerform your static review on the provided specification using this exact analytical approach.\n\n/no_think`";
|
|
2
|
+
//# sourceMappingURL=qePersona.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qePersona.d.ts","sourceRoot":"","sources":["../../../src/layers/syscan/qePersona.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,ykIA2CX,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export const QE_PERSONA = `You are a Senior Quality Engineering analyst reviewing system prompt specifications. Your sole job is to find what is NOT covered — missing boundaries, unhandled edge cases, or negative constraint traps.
|
|
2
|
+
|
|
3
|
+
RULES:
|
|
4
|
+
- Do NOT adopt the persona of the system prompt.
|
|
5
|
+
- Do NOT respond in JSON. For each gap, output exactly:
|
|
6
|
+
GAP: [one-line summary]
|
|
7
|
+
WHY: [one-line explanation]
|
|
8
|
+
- Do NOT assume a broad instruction (e.g. "only do X") acts as a fallback for a forbidden action. If the spec tells the AI what NOT to do, it MUST define the exact conversational response or script it should say instead.
|
|
9
|
+
- Only return 'No gaps found' if EVERY forbidden action has an explicit fallback script AND EVERY out-of-scope input has defined handling. If even one forbidden action lacks a fallback, flag it.
|
|
10
|
+
- Do NOT flag in-scope user questions. If a user asks something that falls within the agent's defined role and domain, the agent handles it by design — that is NOT a gap. A fitness coach handles fitness questions. A SQL generator handles SQL requests. Only flag gaps where the prompt explicitly forbids something without defining a fallback, or where out-of-scope inputs have no defined handling.
|
|
11
|
+
- Do NOT invent user scenarios that the prompt does not address. Only flag gaps that represent a realistic production failure — where the system would break, go silent, or produce harmful output.
|
|
12
|
+
|
|
13
|
+
NOTE: The examples below show reasoning patterns. Apply the pattern, not the content — gaps must come from the specification under review, not from example topics.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
FEW-SHOT TRAINING EXAMPLES
|
|
17
|
+
---
|
|
18
|
+
EXAMPLE 1 — Negative constraint trap (flag this):
|
|
19
|
+
INPUT SPEC: "You are a Python assistant. Write code functions. Never explain anything."
|
|
20
|
+
GAP: Missing instructions for non-technical user questions or prompt injection attacks.
|
|
21
|
+
WHY: The system forces the model to generate Python syntax even from raw text noise or malicious payloads, resulting in syntax errors or crashes in production.
|
|
22
|
+
|
|
23
|
+
EXAMPLE 2 — Banned topic with no fallback script (flag this):
|
|
24
|
+
INPUT SPEC: "You are a travel assistant. Help users plan trips and itineraries. Never discuss visa requirements or immigration processes."
|
|
25
|
+
GAP: Missing explicit conversational fallback when a traveller asks about visa requirements.
|
|
26
|
+
WHY: The spec bans a high-demand topic but defines no response, leaving the agent silent at the exact moment a traveller needs guidance — breaking trust and potentially causing a missed booking.
|
|
27
|
+
|
|
28
|
+
EXAMPLE 3 — In-scope questions are NOT gaps, but missing scope boundary IS (flag only the real gap):
|
|
29
|
+
INPUT SPEC: "You are an expert fitness coach. Design science-based workout programs. Use progressive overload. Deload every 4-6 weeks is mandatory."
|
|
30
|
+
NOT A GAP: A user asking about deload rationale, kettlebell benefits, or exercise selection — these are in-scope fitness questions the coach handles by design.
|
|
31
|
+
GAP: Missing handling for out-of-scope inputs such as nutrition advice, injury diagnosis, or supplement recommendations — the prompt defines no boundary or fallback for these domains.
|
|
32
|
+
WHY: The spec defines a training role but sets no scope boundary, leaving the agent without a defined response when users push into adjacent domains it was not designed to cover.
|
|
33
|
+
|
|
34
|
+
EXAMPLE 4 — Multiple forbidden actions, each needs its own fallback (flag all):
|
|
35
|
+
INPUT SPEC: "You are a customer service agent for an airline. Never discuss compensation claims. Never discuss flight delays. Only answer booking questions."
|
|
36
|
+
GAP 1: No defined redirect when a customer raises a compensation claim.
|
|
37
|
+
WHY: A legally sensitive topic is banned with no script, leaving the agent silent or improvising on a liability-bearing issue.
|
|
38
|
+
GAP 2: Delayed-flight passengers have no handling path — a banned topic the spec leaves entirely undefined.
|
|
39
|
+
WHY: Flight disruptions carry urgency and emotional load; an agent with no response for this scenario risks escalating customer frustration at the worst moment.
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
Perform your static review on the provided specification using this exact analytical approach.
|
|
43
|
+
|
|
44
|
+
/no_think\``;
|
|
45
|
+
//# sourceMappingURL=qePersona.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qePersona.js","sourceRoot":"","sources":["../../../src/layers/syscan/qePersona.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YA2Cd,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixSuggestions.d.ts","sourceRoot":"","sources":["../../src/scorer/fixSuggestions.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA6BjD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const fixSuggestions = {
|
|
2
|
+
NO_ACTIONABLE_INTENT: "Start with a clear action verb (e.g. write, fix, create, update) describing what you want done.",
|
|
3
|
+
FLAKE_RISK_GEO: "Consider integration or E2E tests instead of unit tests for browser-dependent APIs.",
|
|
4
|
+
BROWSER_API_RISK: "Consider integration or E2E tests instead of unit tests for browser-dependent APIs.",
|
|
5
|
+
MISSING_FRAMEWORK: "Specify a test framework (e.g. Vitest, Jest).",
|
|
6
|
+
MISSING_MOCK_STRATEGY: "Specify how external dependencies should be mocked (e.g. using nock, sinon, or jest.mock).",
|
|
7
|
+
MISSING_OUTPUT_FORMAT: "Specify the desired output format (e.g. JSON, markdown, bulleted list).",
|
|
8
|
+
MISSING_SCOPE: "Name the specific file, function, or component instead of using vague references like 'my app' or 'this feature'.",
|
|
9
|
+
HEDGE_DETECTED: "Remove hedge words (maybe, perhaps, kind of) to state the requirement directly.",
|
|
10
|
+
PASSIVE_VOICE: "Use active voice instead of passive constructions for clearer instructions.",
|
|
11
|
+
PRONOUN_AMBIGUITY: "Replace ambiguous pronouns (it, this, that) with the specific noun they refer to.",
|
|
12
|
+
NEGATION_DENSITY: "Restate negative instructions as positive ones where possible (say what TO do, not just what NOT to do).",
|
|
13
|
+
CHAINED_INTENT: "Split this into separate, single-intent requests.",
|
|
14
|
+
TOKEN_BLOAT: "Remove filler phrases and unnecessary preamble to make the instruction more direct.",
|
|
15
|
+
FRUSTRATION_DETECTED: "Take a breath before sending this — frustrated prompts often skip details. Try restating what's broken and what you expected.",
|
|
16
|
+
SEMANTIC_LOW_QUALITY: "Restate the prompt with a specific subject, action, and context (e.g. 'fix the login timeout bug in AuthService.ts').",
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=fixSuggestions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixSuggestions.js","sourceRoot":"","sources":["../../src/scorer/fixSuggestions.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAA2B;IACpD,oBAAoB,EAClB,iGAAiG;IACnG,cAAc,EACZ,qFAAqF;IACvF,gBAAgB,EACd,qFAAqF;IACvF,iBAAiB,EAAE,+CAA+C;IAClE,qBAAqB,EACnB,4FAA4F;IAC9F,qBAAqB,EACnB,yEAAyE;IAC3E,aAAa,EACX,mHAAmH;IACrH,cAAc,EACZ,iFAAiF;IACnF,aAAa,EACX,6EAA6E;IAC/E,iBAAiB,EACf,mFAAmF;IACrF,gBAAgB,EACd,0GAA0G;IAC5G,cAAc,EAAE,mDAAmD;IACnE,WAAW,EACT,qFAAqF;IACvF,oBAAoB,EAClB,+HAA+H;IACjI,oBAAoB,EAClB,uHAAuH;CAC1H,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface Issue {
|
|
2
|
+
severity: 'critical' | 'warning';
|
|
3
|
+
code: string;
|
|
4
|
+
message: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ScoreResult {
|
|
7
|
+
overall: number;
|
|
8
|
+
dimensions: {
|
|
9
|
+
ambiguity: number;
|
|
10
|
+
tokenBloat: number;
|
|
11
|
+
clarity: number;
|
|
12
|
+
riskSignals: number;
|
|
13
|
+
};
|
|
14
|
+
issues: Issue[];
|
|
15
|
+
suggestedFixes: string[];
|
|
16
|
+
}
|
|
17
|
+
export interface ErrorResult {
|
|
18
|
+
error: true;
|
|
19
|
+
code: string;
|
|
20
|
+
message: string;
|
|
21
|
+
}
|
|
22
|
+
export declare function score(prompt: string): ScoreResult | ErrorResult;
|
|
23
|
+
//# sourceMappingURL=scorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scorer.d.ts","sourceRoot":"","sources":["../../src/scorer/scorer.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,KAAK;IACpB,QAAQ,EAAE,UAAU,GAAG,SAAS,CAAA;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE;QACV,SAAS,EAAE,MAAM,CAAA;QACjB,UAAU,EAAE,MAAM,CAAA;QAClB,OAAO,EAAE,MAAM,CAAA;QACf,WAAW,EAAE,MAAM,CAAA;KACpB,CAAA;IACD,MAAM,EAAE,KAAK,EAAE,CAAA;IACf,cAAc,EAAE,MAAM,EAAE,CAAA;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,IAAI,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB;AAMD,wBAAgB,KAAK,CAAC,MAAM,EAAE,MAAM,GAAG,WAAW,GAAG,WAAW,CAyF/D"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { hedgeDetector } from '../layers/linguistic/hedgeDetector.js';
|
|
2
|
+
import { passiveVoice } from '../layers/linguistic/passiveVoice.js';
|
|
3
|
+
import { pronounAmbiguity } from '../layers/linguistic/pronounAmbiguity.js';
|
|
4
|
+
import { negationDensity } from '../layers/linguistic/negationDensity.js';
|
|
5
|
+
import { chainedIntent } from '../layers/linguistic/chainedIntent.js';
|
|
6
|
+
import { bloatDetector } from '../layers/linguistic/bloatDetector.js';
|
|
7
|
+
import { geoFlakeRisk } from '../layers/heuristics/geoFlakeRisk.js';
|
|
8
|
+
import { browserApiRisk } from '../layers/heuristics/browserApiRisk.js';
|
|
9
|
+
import { missingFramework } from '../layers/heuristics/missingFramework.js';
|
|
10
|
+
import { missingMockStrategy } from '../layers/heuristics/missingMockStrategy.js';
|
|
11
|
+
import { missingOutputFormat } from '../layers/heuristics/missingOutputFormat.js';
|
|
12
|
+
import { missingScope } from '../layers/heuristics/missingScope.js';
|
|
13
|
+
import { noActionableIntent } from '../layers/heuristics/noActionableIntent.js';
|
|
14
|
+
import { frustrationSignal } from '../layers/heuristics/frustrationSignal.js';
|
|
15
|
+
import { fixSuggestions } from './fixSuggestions.js';
|
|
16
|
+
function clamp(n) {
|
|
17
|
+
return Math.max(0, Math.min(100, n));
|
|
18
|
+
}
|
|
19
|
+
export function score(prompt) {
|
|
20
|
+
if (prompt.trim() === '') {
|
|
21
|
+
return { error: true, code: 'EMPTY_PROMPT', message: 'Prompt cannot be empty.' };
|
|
22
|
+
}
|
|
23
|
+
if (prompt.trim().split(/\s+/).length < 3) {
|
|
24
|
+
return { error: true, code: 'PROMPT_TOO_SHORT', message: 'Prompt must be at least 3 words to analyze.' };
|
|
25
|
+
}
|
|
26
|
+
// Linguistic detectors
|
|
27
|
+
const hedge = hedgeDetector(prompt);
|
|
28
|
+
const passive = passiveVoice(prompt);
|
|
29
|
+
const pronoun = pronounAmbiguity(prompt);
|
|
30
|
+
const negation = negationDensity(prompt);
|
|
31
|
+
const chained = chainedIntent(prompt);
|
|
32
|
+
const bloat = bloatDetector(prompt);
|
|
33
|
+
// Heuristic detectors
|
|
34
|
+
const geo = geoFlakeRisk(prompt);
|
|
35
|
+
const browser = browserApiRisk(prompt);
|
|
36
|
+
const noFramework = missingFramework(prompt);
|
|
37
|
+
const noMock = missingMockStrategy(prompt);
|
|
38
|
+
const noOutputFormat = missingOutputFormat(prompt);
|
|
39
|
+
const noScope = missingScope(prompt);
|
|
40
|
+
const noIntent = noActionableIntent(prompt);
|
|
41
|
+
const frustrated = frustrationSignal(prompt);
|
|
42
|
+
// Ambiguity (30%): linguistic hedging + heuristic gaps that leave the prompt unclear
|
|
43
|
+
let ambiguity = 100;
|
|
44
|
+
if (noIntent)
|
|
45
|
+
ambiguity -= 100; // no verb = maximally ambiguous intent
|
|
46
|
+
if (hedge)
|
|
47
|
+
ambiguity -= 15;
|
|
48
|
+
if (pronoun)
|
|
49
|
+
ambiguity -= 15;
|
|
50
|
+
if (noScope)
|
|
51
|
+
ambiguity -= 70;
|
|
52
|
+
if (noFramework)
|
|
53
|
+
ambiguity -= 40; // "write tests" with no framework = ambiguous intent
|
|
54
|
+
if (noOutputFormat)
|
|
55
|
+
ambiguity -= 30; // generation task with no format = ambiguous expectation
|
|
56
|
+
ambiguity = clamp(ambiguity);
|
|
57
|
+
// Token Bloat (20%): filler phrase density, repetition, preamble
|
|
58
|
+
let tokenBloat = 100;
|
|
59
|
+
if (bloat)
|
|
60
|
+
tokenBloat -= 50;
|
|
61
|
+
tokenBloat = clamp(tokenBloat);
|
|
62
|
+
// Clarity (30%): passive voice, negation chains, chained intents, frustration
|
|
63
|
+
let clarity = 100;
|
|
64
|
+
if (passive)
|
|
65
|
+
clarity -= 25;
|
|
66
|
+
if (negation)
|
|
67
|
+
clarity -= 25;
|
|
68
|
+
if (chained.flagged)
|
|
69
|
+
clarity -= 25;
|
|
70
|
+
if (frustrated)
|
|
71
|
+
clarity -= 15;
|
|
72
|
+
clarity = clamp(clarity);
|
|
73
|
+
// Risk Signals (20%): critical detectors zero the dimension; warnings deduct
|
|
74
|
+
let riskSignals;
|
|
75
|
+
if (geo || browser) {
|
|
76
|
+
riskSignals = 0;
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
riskSignals = 100;
|
|
80
|
+
if (noMock)
|
|
81
|
+
riskSignals -= 30;
|
|
82
|
+
riskSignals = clamp(riskSignals);
|
|
83
|
+
}
|
|
84
|
+
const issues = [];
|
|
85
|
+
if (noIntent)
|
|
86
|
+
issues.push({ severity: 'critical', code: 'NO_ACTIONABLE_INTENT', message: 'No action verb found — the prompt does not specify what to do.' });
|
|
87
|
+
if (geo)
|
|
88
|
+
issues.push({ severity: 'critical', code: 'FLAKE_RISK_GEO', message: 'Geolocation APIs are browser-dependent — unit testing is flake-prone. Consider integration or E2E tests instead.' });
|
|
89
|
+
if (browser)
|
|
90
|
+
issues.push({ severity: 'critical', code: 'BROWSER_API_RISK', message: 'Browser APIs (navigator/window/document) are unreliable in unit test environments.' });
|
|
91
|
+
if (noFramework)
|
|
92
|
+
issues.push({ severity: 'warning', code: 'MISSING_FRAMEWORK', message: 'No test framework specified. Add: Jest, Vitest, or other.' });
|
|
93
|
+
if (noMock)
|
|
94
|
+
issues.push({ severity: 'warning', code: 'MISSING_MOCK_STRATEGY', message: 'External dependency mentioned but no mock strategy specified.' });
|
|
95
|
+
if (noOutputFormat)
|
|
96
|
+
issues.push({ severity: 'warning', code: 'MISSING_OUTPUT_FORMAT', message: 'No output format specified for generation task.' });
|
|
97
|
+
if (noScope)
|
|
98
|
+
issues.push({ severity: 'warning', code: 'MISSING_SCOPE', message: "Scope too broad — 'my app' / 'my feature' is not specific enough." });
|
|
99
|
+
if (hedge)
|
|
100
|
+
issues.push({ severity: 'warning', code: 'HEDGE_DETECTED', message: 'Hedge words reduce instruction clarity.' });
|
|
101
|
+
if (passive)
|
|
102
|
+
issues.push({ severity: 'warning', code: 'PASSIVE_VOICE', message: 'Passive voice weakens instruction clarity.' });
|
|
103
|
+
if (pronoun)
|
|
104
|
+
issues.push({ severity: 'warning', code: 'PRONOUN_AMBIGUITY', message: 'Unresolved pronoun references reduce clarity.' });
|
|
105
|
+
if (negation)
|
|
106
|
+
issues.push({ severity: 'warning', code: 'NEGATION_DENSITY', message: 'Excessive negation makes instructions harder to follow.' });
|
|
107
|
+
if (chained.flagged)
|
|
108
|
+
issues.push({ severity: 'warning', code: 'CHAINED_INTENT', message: 'Multiple requests chained — consider splitting into separate prompts.' });
|
|
109
|
+
if (bloat)
|
|
110
|
+
issues.push({ severity: 'warning', code: 'TOKEN_BLOAT', message: 'Filler phrases or unnecessary preamble detected.' });
|
|
111
|
+
if (frustrated)
|
|
112
|
+
issues.push({ severity: 'warning', code: 'FRUSTRATION_DETECTED', message: 'Prompt contains frustration signals — stressed prompts often skip important details.' });
|
|
113
|
+
const weighted = ambiguity * 0.3 + tokenBloat * 0.2 + clarity * 0.3 + riskSignals * 0.2;
|
|
114
|
+
const hasCritical = issues.some((i) => i.severity === 'critical');
|
|
115
|
+
const overall = hasCritical ? Math.min(weighted, 59) : weighted;
|
|
116
|
+
const suggestedFixes = [...new Set(issues.flatMap((i) => {
|
|
117
|
+
const fix = fixSuggestions[i.code];
|
|
118
|
+
return fix ? [fix] : [];
|
|
119
|
+
}))];
|
|
120
|
+
return { overall, dimensions: { ambiguity, tokenBloat, clarity, riskSignals }, issues, suggestedFixes };
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=scorer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scorer.js","sourceRoot":"","sources":["../../src/scorer/scorer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAA;IAChB,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "promptvet-core",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Analyze LLM prompts before you send them.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"promptvet": "dist/cli/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"prepublishOnly": "npm run build",
|
|
12
|
+
"test": "vitest run",
|
|
13
|
+
"test:watch": "vitest",
|
|
14
|
+
"test:coverage": "vitest run --coverage",
|
|
15
|
+
"typecheck": "tsc --noEmit"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@huggingface/transformers": "^3.0.0",
|
|
19
|
+
"commander": "^12.1.0",
|
|
20
|
+
"node-llama-cpp": "^3.18.1"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/node": "^25.9.3",
|
|
24
|
+
"@vitest/coverage-v8": "^2.1.0",
|
|
25
|
+
"typescript": "^5.5.0",
|
|
26
|
+
"vitest": "^2.1.0"
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=22"
|
|
30
|
+
},
|
|
31
|
+
"overrides": {
|
|
32
|
+
"@huggingface/transformers": {
|
|
33
|
+
"onnxruntime-node": "1.20.1"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"README.md"
|
|
39
|
+
],
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
}
|
|
43
|
+
}
|