Appendix B · section 32 of 32
ask/pipeline.test.ts
From Tests That Never Call the Model.
import test from "node:test";
import assert from "node:assert/strict";
import type { Ask, Reply, Turn } from "./answer.js";
import { LAWS, type Law } from "./corpus.js";
import { answerQuestion } from "./pipeline.js";
import { ROWS } from "./schedule.js";
// The one property the pipeline exists to keep: what the model writes is not
// what the learner sees unless it passes the checks. Every test drives a
// model that says the wrong thing on purpose, or a stage that fails on
// purpose, and asserts what reached the screen and what the log says.
interface Call {
question: string;
laws: Law[];
history: Turn[];
}
/** A model that answers from a script, and records what it was asked. */
function model(...replies: Reply[]): { ask: Ask; calls: Call[] } {
const calls: Call[] = [];
let next = 0;
return {
calls,
ask: async (question, laws, history) => {
calls.push({ question, laws, history });
const reply = replies[Math.min(next, replies.length - 1)] ?? { kind: "failed", why: "unreachable" };
next += 1;
return reply;
},
};
}
const says = (answer: string, sources: string[], scope: "road-law" | "other" = "road-law"): Reply => ({
kind: "reply",
scope,
answer,
sources,
});
const HYDRANT = "how far from a fire hydrant can i park";
const ids = (laws: Law[]): string[] => laws.map((law) => law.id);
test("an answer that cites a law it was given is shown, under that law's own citation", async () => {
const { ask, calls } = model(says("Stay at least 15 feet from a hydrant.", ["MD-S01"]));
const { body, outcome } = await answerQuestion(HYDRANT, [], { ask, laws: LAWS });
assert.ok(ids(calls[0].laws).includes("MD-S01"));
assert.equal(body.id, "answer");
if (body.id === "answer") {
assert.equal(body.citations[0].id, "MD-S01");
assert.ok(body.citations[0].location.startsWith("Md. Code, Transp. § 21-1003(m)"));
assert.equal(body.citations[0].asOf, "2026-10-05");
}
assert.deepEqual(outcome.sources, ["MD-S01"]);
});
test("a law nobody gave it is refused, and the log says why", async () => {
const { ask } = model(says("Stay at least 15 feet from a hydrant.", ["MD-S99"]));
const { body, outcome } = await answerQuestion(HYDRANT, [], { ask, laws: LAWS });
assert.equal(body.id, "no-match");
assert.equal(outcome.answer, "");
assert.equal(outcome.model, "road-law:uncited");
});
test("an invented figure is refused", async () => {
const { ask } = model(says("Stay at least 20 feet from a hydrant.", ["MD-S01"]));
const { outcome } = await answerQuestion(HYDRANT, [], { ask, laws: LAWS });
assert.equal(outcome.model, "road-law:ungrounded");
});
test("the index throwing leaves retrieval by words, and the answer is still shown", async () => {
const { ask, calls } = model(says("Stay at least 15 feet from a hydrant.", ["MD-S01"]));
const near = async (): Promise<string[]> => {
throw new Error("the index is down");
};
const { body } = await answerQuestion(HYDRANT, [], { ask, laws: LAWS, near });
assert.equal(body.id, "answer");
assert.ok(ids(calls[0].laws).includes("MD-S01"));
});
test("an id the index holds that the corpus does not is never given to the model", async () => {
const { ask, calls } = model(says("Stay at least 15 feet from a hydrant.", ["MD-S01"]));
const near = async (): Promise<string[]> => ["MD-GONE", "MD-S01"];
await answerQuestion(HYDRANT, [], { ask, laws: LAWS, near });
assert.ok(!ids(calls[0].laws).includes("MD-GONE"));
assert.ok(ids(calls[0].laws).includes("MD-S01"));
});
test("the rephraser failing is retrieval on the question alone", async () => {
const { ask } = model(says("Stay at least 15 feet from a hydrant.", ["MD-S01"]));
const rephrase = async (): Promise<string[]> => {
throw new Error("timed out");
};
const { body } = await answerQuestion(HYDRANT, [], { ask, laws: LAWS, rephrase });
assert.equal(body.id, "answer");
});
test("the reranker failing gives the model exactly what it got before the reranker existed", async () => {
const plain = model(says("Stay at least 15 feet from a hydrant.", ["MD-S01"]));
await answerQuestion(HYDRANT, [], { ask: plain.ask, laws: LAWS });
const failing = model(says("Stay at least 15 feet from a hydrant.", ["MD-S01"]));
const rerank = async (): Promise<number[]> => {
throw new Error("the reranker is down");
};
await answerQuestion(HYDRANT, [], { ask: failing.ask, laws: LAWS, rerank });
assert.deepEqual(ids(failing.calls[0].laws), ids(plain.calls[0].laws));
});
test("the reranker's choice is what the model reads first", async () => {
const { ask, calls } = model(says("Stay 20 feet from a fire station driveway.", ["MD-S05"]));
const rerank = async (_question: string, texts: string[]): Promise<number[]> =>
texts.map((text) => (text.includes("fire station driveway") ? 5 : Number.NEGATIVE_INFINITY));
const { body } = await answerQuestion(HYDRANT, [], { ask, laws: LAWS, rerank });
assert.equal(calls[0].laws[0].id, "MD-S05");
assert.equal(body.id, "answer");
});
test("a chosen subsection brings its section and the schedule's row, whose figure grounds the answer", async () => {
const { ask, calls } = model(says("You'll get a $50 ticket you can pay by mail, with no points.", ["MD-P-16-112-b"]));
const rerank = async (_question: string, texts: string[]): Promise<number[]> =>
texts.map((text) => (text.startsWith("(b) Each individual driving") ? 5 : Number.NEGATIVE_INFINITY));
const { body } = await answerQuestion("what happens if i get pulled over without my license", [], {
ask,
laws: LAWS,
rerank,
penalties: ROWS,
});
const given = ids(calls[0].laws);
for (const id of ["MD-C-16-112-b", "MD-C-16-112-c", "MD-C-16-112-d", "MD-C-16-112-e", "MD-P-16-112-b"]) {
assert.ok(given.includes(id), id);
}
assert.equal(body.id, "answer");
if (body.id === "answer") assert.equal(body.citations[0].kind, "penalty");
});
test("without the schedule, the same question is given the section and nothing invented", async () => {
const { ask, calls } = model(says("You'll get a $50 ticket.", ["MD-C-16-112-b"]));
const { outcome } = await answerQuestion("what happens if i get pulled over without my license", [], { ask, laws: LAWS });
assert.ok(!ids(calls[0].laws).some((id) => id.startsWith("MD-P-")));
assert.equal(outcome.model, "road-law:ungrounded");
});
test("a question outside road law gets the pipeline's own line, never the model's words", async () => {
const { ask } = model(says("Paris.", [], "other"));
const { body, outcome } = await answerQuestion("what is the capital of France", [], { ask, laws: LAWS });
assert.equal(body.id, "no-match");
if (body.id === "no-match") assert.ok(!body.pointer.includes("Paris"));
assert.equal(outcome.model, "scope:other");
});
test("a model outage is named, not answered", async () => {
const { ask } = model();
const { body, outcome } = await answerQuestion(HYDRANT, [], { ask, laws: LAWS });
assert.equal(body.id, "no-match");
assert.equal(outcome.model, "unreachable");
});
test("the thread reaches the model as the learner saw it", async () => {
const { ask, calls } = model(says("Yes, 15 feet.", ["MD-S01"]));
const history: Turn[] = [{ question: HYDRANT, answer: "Stay at least 15 feet from a hydrant.", sources: ["MD-S01"] }];
await answerQuestion("is that measured from the curb", history, { ask, laws: LAWS });
assert.deepEqual(calls[0].history, history);
});