fix(prompt): drop HOUSE_STYLE — the shipped prompt now says it itself

HOUSE_STYLE was appended after tutor-system.md because the old prompt
never stated which language to teach in, and gpt-oss-20b delivered a
unit-1.1 lesson in Korean. The 16 Sep prompt states the rule outright,
twice — "everything you SAY is in English" — and the client now has
proseIsKorean() to send a Korean explanation back. The appendix said
itself that if the shipped prompt ever covered this, it should go.

{{VARIETY}} also learns the fifth exercise type, recall.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
MechaCat02
2026-09-16 19:50:15 +02:00
parent ba3055912a
commit 04a0900a2c

View File

@@ -112,8 +112,8 @@ export function gateFor({ progress, bandQuery }: GateInputs): Gate {
/* ── the prompt ──────────────────────────────────────────────────── */ /* ── the prompt ──────────────────────────────────────────────────── */
/** The four exercise types, so {{VARIETY}} can ask for a different one. */ /** The five exercise types, so {{VARIETY}} can ask for a different one. */
const TASK_TYPES = ["translate", "match", "build", "choice"] as const; const TASK_TYPES = ["translate", "recall", "match", "build", "choice"] as const;
export type TaskKind = (typeof TASK_TYPES)[number]; export type TaskKind = (typeof TASK_TYPES)[number];
export const FOCUS_MODES = { export const FOCUS_MODES = {
@@ -150,34 +150,6 @@ export interface PromptInputs {
focus: FocusMode; focus: FocusMode;
} }
/**
* Assemble the system prompt. The template is prompt/tutor-system.md,
* shipped unchanged — this fills its three placeholders and nothing else.
*/
/* Appended by the app, after the shipped prompt — not an edit to it.
tutor-system.md ships unchanged. Two things it leaves to inference, which
a strong model supplies on its own and a small local one does not:
THE LANGUAGE OF EXPLANATION is never actually stated. The prompt says
"한글 and English only", but that rule is about retiring romanization, not
about which language to teach in. Everything else only implies it —
English translations, English glosses. gpt-oss-20b read the room
differently and delivered a whole grammar lesson in Korean, to a student
on unit 1.1 who cannot yet read it.
NO MARKDOWN is stated outright at line 96, and was ignored anyway. It is
restated here because the consequence is invisible to the model: the app
renders **bold** and nothing else, so a table arrives as rows of literal
pipes and a heading as literal hashes.
Both are reinforcement, never contradiction. If the shipped prompt and
this ever disagree, the shipped prompt is right and this should go. */
const HOUSE_STYLE = `
════ HOUSE STYLE ════
Explain in English. Korean is the material — words, examples, exercise lines, anything you are asking him to read. It is not the language you teach in. He is a beginner working through the writing system; an explanation he cannot read teaches him nothing.
Plain text only. No tables, headings, bullet characters or code fences — the app renders **bold** and nothing else, so anything else reaches him as literal pipes and hashes.`;
/** /**
* Substitute one placeholder — the one standing alone on its own line. * Substitute one placeholder — the one standing alone on its own line.
* *
@@ -207,11 +179,15 @@ function fill(template: string, name: string, value: string): string {
return template.replace(token, () => value); return template.replace(token, () => value);
} }
/**
* Assemble the system prompt. The template is prompt/tutor-system.md,
* shipped unchanged — this fills its three placeholders and nothing else.
*/
export function assemblePrompt({ template, gate, recent, focus }: PromptInputs): string { export function assemblePrompt({ template, gate, recent, focus }: PromptInputs): string {
let out = fill(template, "GATE", renderGate(gate)); let out = fill(template, "GATE", renderGate(gate));
out = fill(out, "VARIETY", varietyLine(recent)); out = fill(out, "VARIETY", varietyLine(recent));
out = fill(out, "FOCUS", focusLine(focus)); out = fill(out, "FOCUS", focusLine(focus));
return out + HOUSE_STYLE; return out;
} }
export { renderGate, REFERENCE_BAND }; export { renderGate, REFERENCE_BAND };