practice live-test fixes — scroll containers, session math delimiters, header guidance, sweep heartbeat (owner live test 2026-09-29)
This commit is contained in:
@@ -232,10 +232,11 @@ export function createPracticePipeline(deps: PracticePipelineDeps) {
|
||||
// 1. ONCE PER PROCESS (globalThis flag) — an instance could otherwise
|
||||
// evaluate against a registry whose fresh row it can't observe
|
||||
// (dev route bundles, restart paths).
|
||||
// 2. GRACE WINDOW (120s over updatedAt ?? createdAt) — a live run
|
||||
// saves at every phase/problem transition, so its heartbeat is
|
||||
// structurally never 120s stale; a true orphan is minutes stale at
|
||||
// the next boot.
|
||||
// 2. GRACE WINDOW (120s over updatedAt ?? createdAt) — a live run's
|
||||
// WATCHDOG re-stamps the file every 30s (cross-worker liveness —
|
||||
// the registry is NOT shared between dev route workers), so a
|
||||
// live run is structurally never 120s stale; a true crash stops
|
||||
// the beats and is minutes stale at the next boot.
|
||||
// 3. Live-row check (globalThis-shared registry) as before.
|
||||
const sweepFlag = globalThis as { __lhPracticeSweepDone?: boolean };
|
||||
if (!sweepFlag.__lhPracticeSweepDone) {
|
||||
@@ -275,6 +276,26 @@ export function createPracticePipeline(deps: PracticePipelineDeps) {
|
||||
): Promise<void> {
|
||||
const controller = partitionRow.controller;
|
||||
|
||||
// PERSISTENT HEARTBEAT (owner live test #2, 2026-09-29 — the sweep
|
||||
// stamped LIVE runs again): dev serves routes from workers that do
|
||||
// NOT share this process's registry, so memory liveness cannot
|
||||
// protect a cross-worker sweep, and a long-running last problem can
|
||||
// exceed the 120s grace between store writes. The watchdog
|
||||
// re-stamps updatedAt on the FILE every 30s while THIS run is live
|
||||
// (4-beat tolerance inside the grace window) — any process's sweep
|
||||
// then sees a fresh heartbeat; a true crash stops the beats and the
|
||||
// orphan goes stale honestly.
|
||||
const beat = setInterval(() => {
|
||||
void withSetLock(set.id, () => {
|
||||
const cur = deps.practiceStore.getSet(set.id);
|
||||
if (!cur) return;
|
||||
if (cur.status !== "partitioning" && cur.status !== "generating") return;
|
||||
deps.practiceStore.saveSet(cur);
|
||||
});
|
||||
}, 30_000);
|
||||
beat.unref?.();
|
||||
|
||||
try {
|
||||
// Stage 1 — the partitioner (its OWN dock row; acquires a shared
|
||||
// permit like every background LLM job).
|
||||
let partitions: Array<{ chains: string[] }>;
|
||||
@@ -393,6 +414,9 @@ export function createPracticePipeline(deps: PracticePipelineDeps) {
|
||||
cur.error = undefined;
|
||||
deps.practiceStore.saveSet(cur);
|
||||
});
|
||||
} finally {
|
||||
clearInterval(beat);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -188,7 +188,7 @@ INPUTS (in the user message):
|
||||
THE CUE DISTANCE: 0 Lesson context · 1 Adjacent context · 2 Far context — how far the situation sits from the cues the learner has already met: the lesson's own examples AND every previous problem's situation. Far context is the edge of the recognizable band — the proposition must still genuinely apply, and the learner must be able to find it by looking.
|
||||
THE PRESENTATION: Theory (the subject's own terms — symbols, formal objects, native vocabulary) or Application (a concrete worldly affair in which the proposition's structure appears in the wild). It dresses the situation; it never changes the rung or the cue distance.
|
||||
Apply Part II step 2: degrade honestly if the target cannot support them — the degradation shows in the problem's own shape, never in meta-commentary.
|
||||
- FORMATTING: your statement, solution, and rubric are rendered as full Markdown — use everything it offers. Mathematics is always LaTeX: inline as $…$, display as $$…$$ on its own lines. Code, pseudocode, and formal systems live in fenced code blocks with a language tag; identifiers and symbols inline as \`code\`. Use tables for parallel structure and comparisons, lists for enumerations. Prose-only renderings of mathematical or structured content are a defect: if a sentence carries an equation, a derivation, or a piece of code, format it as what it is.
|
||||
- FORMATTING: your statement, solution, and rubric are rendered as full Markdown — use everything it offers. Mathematics is always LaTeX: inline as \\(…\\), display as \\[…\\] on its own lines — a bare $ is literal currency and never starts math. Inside math, use LaTeX commands for symbols, not unicode stand-ins (they fail to render). Code, pseudocode, and formal systems live in fenced code blocks with a language tag; identifiers and symbols inline as \`code\`. Use tables for parallel structure and comparisons, lists for enumerations. Skip headers — at this size they are pointless decoration; structure with paragraphs, bold labels, and lists (a genuinely long derivation may earn one). Prose-only renderings of mathematical or structured content are a defect: if a sentence carries an equation, a derivation, or a piece of code, format it as what it is.
|
||||
- PREVIOUS PROBLEMS: problems the learner has already answered, with the chains they exercised. Do not rebuild one; keep your situation distant from theirs — cue distance counts previous problems' situations (Part I, "Cue distance").
|
||||
|
||||
OUTPUT — your entire deliverable is ONE submit_problem call:
|
||||
@@ -228,7 +228,7 @@ THE VERDICT (exactly one):
|
||||
- "partial": some of the target came to mind; the answer is materially incomplete or partly wrong.
|
||||
- "missed": the targeted proposition(s) did not come to mind — the answer is empty or on the wrong track.
|
||||
|
||||
Feedback renders as full Markdown. Mathematics is always LaTeX — inline as $…$, display as $$…$$ on its own lines. Code in fenced blocks with a language tag, identifiers inline as \`code\`. Lists and tables wherever they carry structure. Name the failed recall and teach the boundary in properly formatted prose, not plain text.
|
||||
Feedback renders as full Markdown. Mathematics is always LaTeX — inline as \\(…\\), display as \\[…\\] on its own lines (a bare $ is literal currency). Inside math, LaTeX commands for symbols, not unicode stand-ins. Code in fenced blocks with a language tag, identifiers inline as \`code\`. Lists and tables wherever they carry structure; no headers — feedback is short-form, structure it with paragraphs and bold labels. Name the failed recall and teach the boundary in properly formatted prose, not plain text.
|
||||
|
||||
OUTPUT — your entire deliverable is ONE submit_grade call: "verdict" and "feedback" (non-empty; the boundary-teaching text above).`;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user