math: dollar delimiters end-to-end (exact answers, escaping examples, context rendering)
- switch the math authoring/rendering contract from \(...\)/\[...\] to the standard $...$ inline / $$...$$ display: prompts (20-question-tools, 40-formatting), singleDollarTextMath on the renderer, legacy reader kept, and escape-debris recovery extended to dollar spans (mirroring micromark delimiter-run rules) - exact answer membership now precedes debris cleanup in coerceCorrectAnswer (calculus incident: an exact sentence-final-period label was stripped as model debris, then rejected); option keys are passed at the boundary/grading seams, the dock no longer pre-coerces - a complete, phase-correct JSON-escaping example rides the probe/quiz tool descriptions (serialized from one canonical body; quiz leads with type+nodeId), plus the one-sentence JSON-escaping rule in 40-formatting - ask option descriptions render markdown/LaTeX in the pending dock; settled cards keep the details line and option descriptions retroactively, read from the persisted call arguments (chat passes part.input to AnsweredCard) 1566/1566 tests on both navigator configs; typecheck, lint, production build, standalone packaging, and Electron-runtime smoke all green.
This commit is contained in:
@@ -70,7 +70,7 @@ export function listSourceSegments(agent: PromptAgent): Array<{ path: string; sh
|
||||
// file mechanics stay out (the doctrine contradicts them; 00-base.md
|
||||
// plays the base role), but the FORMATTING guide composes for every
|
||||
// agent (owner, 2026-10-04 late): LaTeX delimiters and markdown apply
|
||||
// in all settings — practice must write \(...\)/\[...\] too.
|
||||
// in all settings — practice shares the $...$/$$...$$ authoring contract.
|
||||
const segments: Array<{ path: string; shared: boolean; file: string }> = agent === "practice" ? [] : [
|
||||
{ path: "system-prompt.md", shared: true, file: PATHS.teacherPrompt },
|
||||
];
|
||||
|
||||
@@ -7,7 +7,7 @@ Two instruments. The quiz tool (its exact name depends on the quizzing mechanic
|
||||
Applies to every graded question you ask, whatever its role:
|
||||
|
||||
- Multiple choice carries a separate `explanation` (why the correct option is correct, written BEFORE `correctAnswer`: reason it out first, then commit). Free recall has ONE field — `correctAnswer`, the committed answer with its reasoning inside.
|
||||
- **LaTeX everywhere.** Every question field renders markdown and LaTeX — the question text, every option, every explanation. Anything expressible as math goes in math: formulas, symbols, even single variables (`\(x\)`, `\(\alpha\)`). Plain-text math in a question is a craft failure; `\(...\)` and `\[...\]` are the only delimiters (never `$`).
|
||||
- **LaTeX everywhere.** Every question field renders markdown and LaTeX — the question text, every option, every explanation. Anything expressible as math goes in math: formulas, symbols, even single variables (`$x$`, `$\alpha$`). Plain-text math in a question is a craft failure; use `$...$` for inline math and `$$...$$` on separate lines for display math.
|
||||
- **The option craft.** The giveaway is never the distractors' wrongness, it's asymmetry: the correct option carrying its reasoning while the others are bare, or key-term bolding that flags it. Build evenness in: (1) every option is a bare claim — zero "why" in any of them; all reasoning goes in the explanation, shown only after he answers; (2) write the correct claim first, then mutate it into each distractor — what would someone holding a specific misconception claim? Same skeleton, same grain, same register; (3) each distractor is a real, BELIEVABLE error — the answer he would actually give under a specific wrong model, wrong on knowledge, never obviously wrong on sight. An option a cold reader eliminates instantly is a wasted option: his pick is diagnostic only when the wrong model is what selects it; (4) no asymmetric bolding. If you can tell the right one cold without knowing the material, regenerate — don't patch.
|
||||
- **Free-recall grading.** Grade his words strictly against the committed answer; never mark a wrong answer right to be kind — a near-miss is partial understanding: name exactly what he got and what he missed. If he genuinely doesn't know, he says so in his own words — that is a genuine gap, not a wrong answer.
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
Everything you write — every message, every quiz question, every quiz option and explanation — renders as markdown to him, and the full set is available: headings, lists, tables, fenced code, inline code, bold, mermaid diagrams. Use it maximally when it fits — the default is a structured document, not a wall of prose. Headings for the sections a message naturally has; lists and tables for anything enumerable or comparative; code blocks for anything literal. Structure is not decoration — it makes the content readable at a glance — and when in doubt, structure it.
|
||||
|
||||
- Math: anything expressible in LaTeX goes in LaTeX — formulas, symbols, even single variables — everywhere text renders, and that means EVERY field: prose, quiz questions, quiz options, explanations, problem statements, answers. Inline `\(f(x)\)`, display `\[` fenced on its own lines. NEVER `$` or `$$` — a bare `$` is literal currency here; `\(...\)` and `\[...\]` are the only delimiters that render.
|
||||
- Math: anything expressible in LaTeX goes in LaTeX — formulas, symbols, even single variables — everywhere text renders, and that means EVERY field: prose, quiz questions, quiz options, explanations, problem statements, answers. Inline `$f(x)$`, display `$$` fenced on its own lines. Use `$...$` for inline math and `$$...$$` on separate lines for display math. In JSON strings (tool arguments), use `\\` for LaTeX command backslashes, `\\\\` for TeX row breaks, and `\n` for newlines.
|
||||
- Key ideas: a GitHub-style `> [!IMPORTANT]` callout renders as a distinct outlined block — the one emphasis device for load-bearing ideas. Use it sparingly: an unconditional truth as it's laid down, a payoff when it lands, a definition the whole chain hinges on. Everything else stays in prose — if everything is boxed, nothing is.
|
||||
- Diagrams: ```mermaid fenced blocks render as real diagrams — reach for one whenever structure, flow, or relationships are the point; a good diagram beats three paragraphs. Node labels with spaces or symbols must use quoted bracket form (`B["u = x^3"]`).
|
||||
|
||||
+43
-3
@@ -106,12 +106,42 @@ export const askUserQuestionTool: AgentTool<typeof askInputSchema> = {
|
||||
// quiz variants): duplicates stay honest by sharing SCHEMA ATOMS
|
||||
// (question-core) + PROMPT CHUNKS, and each tool declares only its
|
||||
// mechanical delta.
|
||||
//
|
||||
// ONE sanctioned exception (owner, 2026-10-12): each quiz tool's
|
||||
// description ends with a COMPLETE example call — compact, phase-correct
|
||||
// (probe carries no phase metadata; quiz leads with type+nodeId), doubling
|
||||
// as the JSON-escaping exemplar (LaTeX backslashes double inside JSON
|
||||
// strings). Placement ruling: WITH THE TOOL, beside its exact schema — a
|
||||
// shared-prompt example is phase-ambiguous (the models fumbled exactly
|
||||
// these metadata fields), per-agent prompt copies would drift. Serialized
|
||||
// from ONE canonical body so the variants cannot disagree; craft doctrine
|
||||
// stays in the prompts.
|
||||
|
||||
/** The canonical example body (owner-approved content, 2026-10-12): a
|
||||
* compact applied question whose fields exercise the escaping hazards —
|
||||
* braced commands (\frac, \cos), inline and display math, newlines —
|
||||
* while doubling as an exemplar of good craft: uniform options, stable
|
||||
* values, reasoning (explanation) committed before correctAnswer.
|
||||
* JSON.stringify renders the wire text, so the escaping the model sees
|
||||
* is by construction the correct one. Exported for the description pins. */
|
||||
export const quizExampleBody = {
|
||||
question: "A signal is $y=\\sin(2x)$ and $\\frac{dx}{dt}=3$. What is $\\frac{dy}{dt}$?",
|
||||
options: [
|
||||
{ label: "$6\\cos(2x)$", value: "a" },
|
||||
{ label: "$2\\cos(2x)$", value: "b" },
|
||||
{ label: "$3\\cos(2x)$", value: "c" },
|
||||
],
|
||||
explanation:
|
||||
"The phase changes twice as fast as $x$; multiply by the sine's slope:\n$$\n\\frac{dy}{dt}=\\cos(2x)\\cdot2\\cdot3=6\\cos(2x)\n$$",
|
||||
correctAnswer: "a",
|
||||
};
|
||||
|
||||
/** The quiz mechanics every variant shares; `delta` appends the variant's
|
||||
* own fields (its NAME among them — the probe-phase tools self-reference
|
||||
* as probe/recall, owner 2026-10-09). All mechanics, zero doctrine. */
|
||||
* as probe/recall, owner 2026-10-09). All mechanics, zero doctrine — plus
|
||||
* the one sanctioned example (above). */
|
||||
function quizDescription(delta: { name: "quiz" | "probe"; nodeId: boolean; types: boolean }): string {
|
||||
return (
|
||||
const base =
|
||||
"Ask the learner a GRADED question with a known correct answer, then instantly grade and give feedback. " +
|
||||
"Unlike ask_user_question (which collects preferences/decisions with no right answer), " +
|
||||
delta.name +
|
||||
@@ -129,7 +159,17 @@ function quizDescription(delta: { name: "quiz" | "probe"; nodeId: boolean; types
|
||||
: "") +
|
||||
"ONE question per turn: call a single " +
|
||||
delta.name +
|
||||
", then end your turn — his answer determines the next."
|
||||
", then end your turn — his answer determines the next.";
|
||||
// Phase-correct shape: the teach example LEADS with the required pair
|
||||
// (type, nodeId — the 2026-10-09 drop-order ruling); the probe example
|
||||
// carries no phase metadata at all, exactly like the probe schema.
|
||||
const example = delta.nodeId ? { type: "check" as const, nodeId: "chain-rule", ...quizExampleBody } : quizExampleBody;
|
||||
return (
|
||||
base +
|
||||
"\nExample arguments — copy the escaping exactly: inside JSON strings a LaTeX backslash is \\\\ and a newline is \\n.\n```json\n" +
|
||||
JSON.stringify(example, null, 2) +
|
||||
"\n```" +
|
||||
(delta.nodeId ? " The example's nodeId is illustrative — copy an exact id from this session's plan_init." : "")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user