-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathask-corpus.js
More file actions
76 lines (72 loc) · 3.48 KB
/
Copy pathask-corpus.js
File metadata and controls
76 lines (72 loc) · 3.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
/**
* ask-corpus.js — deterministic calibration harness for the Ask engine.
*
* Run: node ask-corpus.js (from this folder; Node only, no deps)
*
* Loads answer() straight out of Agentic-AI-Governance-Chat.html (single source of truth) and
* asserts three things the red-team-style probe surfaced:
* 1. Real terms and their variants (plurals, acronyms, sloppy phrasing) resolve to the RIGHT term.
* 2. A query that only matches a FRAGMENT of a term never confidently returns the wrong one
* ("sandbagging" must not become "Bagging"; "vector store" must not become "Store"). It may
* hit the right term or fall back to closest-matches, but it must not sound sure while wrong.
* 3. A genuine non-term falls back to closest matches (a miss), never a false definition.
* The labels are the floor: when a case fails, fix the matching rules in the HTML, not the label.
*
* License: CC BY 4.0, consistent with the rest of the project.
*/
const fs = require("fs");
const path = require("path");
const vm = require("vm");
const H = require("./corpus-harness.js");
function loadAnswer() {
const lines = fs.readFileSync(path.join(__dirname, "Agentic-AI-Governance-Chat.html"), "utf8").split(/\r?\n/);
const start = lines.findIndex(l => l.trim() === "<script>");
const end = lines.findIndex(l => l.startsWith("const feed="));
if (start < 0 || end < 0) throw new Error("ask-corpus: could not bound the inline script");
const sandbox = { document: { getElementById: () => ({}) }, location: { search: "" }, console };
vm.createContext(sandbox);
vm.runInContext(lines.slice(start + 1, end).join("\n") + "\nthis.answer = answer;", sandbox);
return sandbox.answer;
}
const defName = r => { const m = (r.reading || "").match(/^define\(([^)]*)\)/); return m ? m[1] : null; };
// 1) must resolve to the right term (define == expected)
const HITS = [
["context window", "Context Window"],
["guardrails", "Guardrail"],
["hallucinations", "Hallucination"],
["MCP", "Model Context Protocol"],
["what is RAG?", "Retrieval-Augmented Generation"],
["red teaming", "Red Teaming"],
["tool poisoning", "Tool Poisoning"],
["what is a harness?", "Harness"],
["vector database", "Vector Database"],
["excessive agency", "Excessive Agency"],
];
// 2) must NOT confidently define the wrong (fragment-collision) term
const NOT_WRONG = [
["sandbagging", "Bagging"],
["what is a vector store", "Store"],
["prompt injektion", "Prompt"],
];
// 3) genuine non-term must fall back to a miss, never a false definition
const MISSES = ["what is the meaning of life"];
function run() {
const answer = loadAnswer();
for (const [q, want] of HITS) {
const got = defName(answer(q));
if (got === want) H.pass('resolves "' + q + '" -> ' + want);
else H.fail('resolves "' + q + '"', "wanted define(" + want + "), got " + (got ? "define(" + got + ")" : "no confident define"));
}
for (const [q, forbidden] of NOT_WRONG) {
const got = defName(answer(q));
if (got !== forbidden) H.pass('"' + q + '" does not confidently return the wrong "' + forbidden + '" (got ' + (got ? "define(" + got + ")" : "closest-matches") + ")");
else H.fail('"' + q + '" sounds sure while wrong', "confidently defined " + forbidden);
}
for (const q of MISSES) {
const r = answer(q);
if (r.miss && !defName(r)) H.pass('"' + q + '" falls back to closest matches (honest miss)');
else H.fail('"' + q + '" should be an honest miss', "got define(" + defName(r) + ")");
}
process.exit(H.summarize());
}
run();