ui: round 8 — fuzzy session search, stacked doors, All right, teach divider at the step seam
- SESSION SEARCH goes fuzzy on the SAME fuzzyScore the model pickers use (de0c286's util — one scoring across every search surface): ranked by score instead of raw substring; empty query keeps order. - SIDEBAR: New Teaching / New Practice STACK (full-width rows); the kind filter reads Teaching · Practice · All — the real modes first, All as the escape hatch, mirroring the stack above. Home stays in the LH band (owner-confirmed). - TEACH DIVIDER, the stacked-dividers bug: the plan presentation and the first tagged quiz call usually share ONE assistant message, so the message-level seam drew Planning+Teaching back-to-back. New pure teachStepIndex(parts) finds the STEP boundary governing the flip call; the divider renders there (replacing that boundary's plain hairline — a labeled rule supersedes it), prepending before the whole message only when the flip is in its first step. The fold (chip, sidebar state) is untouched. - JOBS SUITE, flake round 3: the sweep scans the SHARED jobs dir, so parallel test FILES' running records respawn into this file's counters — the assertions go jurisdictional (own-job ids collected; foreign respawns are not this test's business). 1331/1331.
This commit is contained in:
+32
-9
@@ -50,6 +50,7 @@ import {
|
||||
findPendingToolCall,
|
||||
phaseAt3,
|
||||
phaseTimeline,
|
||||
teachStepIndex,
|
||||
toolQuestionKind,
|
||||
quizNeedsReveal,
|
||||
} from "@/src/core";
|
||||
@@ -1238,15 +1239,26 @@ export function Chat({
|
||||
{/* THE INFERRED TEACH SEAM (owner ruling 2026-09-26, the verdict
|
||||
death): teaching begins where the FIRST nodeId-tagged quiz is
|
||||
posed — the fold (phaseTimeline, the same derivation the phase chip
|
||||
reads) flips to teach exactly AT this assistant group, so the divider
|
||||
renders BEFORE the whole block (thinking -> prose -> the quiz call) —
|
||||
where the explicit accept marker used to sit. The boundary check
|
||||
(this index flips, the previous didn't) guarantees exactly ONE divider
|
||||
per session. PREPENDED, never a replacement branch: the teach group is
|
||||
a real message with content (the marker branches above have none) — a
|
||||
replacement ternary swallowed the entire first lesson block (the
|
||||
Lacan session, 2026-09-27). */}
|
||||
{m.role === "assistant" && mi > 0 && phases[mi] === "teach" && phases[mi - 1] !== "teach" ? (
|
||||
reads) flips to teach exactly AT this assistant group. STEP-LEVEL
|
||||
since owner round 8 (2026-10-05 — the stacked-dividers bug): the
|
||||
plan presentation often lives in the SAME message, an earlier
|
||||
provider step than the quiz call, and the old message-level seam
|
||||
drew this divider before the plan too (Planning and Teaching
|
||||
stacked back-to-back, nothing between). teachStepIndex finds the
|
||||
step boundary governing the flip call: -1 = the message's first
|
||||
step → prepend before the whole block (this branch); a later
|
||||
index → the divider renders AT that part boundary in the loop
|
||||
below (replacing the plain step hairline — a labeled phase rule
|
||||
supersedes it). The boundary check (this index flips, the
|
||||
previous didn't) still guarantees exactly ONE divider per session.
|
||||
PREPENDED, never a replacement branch: the teach group is a real
|
||||
message with content — a replacement ternary swallowed the entire
|
||||
first lesson block (the Lacan session, 2026-09-27). */}
|
||||
{m.role === "assistant" &&
|
||||
mi > 0 &&
|
||||
phases[mi] === "teach" &&
|
||||
phases[mi - 1] !== "teach" &&
|
||||
teachStepIndex(m.parts) === -1 ? (
|
||||
<PhaseDivider key={`teach-${m.id || `m-${mi}`}`} phase="teach" />
|
||||
) : null}
|
||||
{m.role === "user" ? (
|
||||
@@ -1273,6 +1285,15 @@ export function Chat({
|
||||
<MessageContent className="w-full">
|
||||
{m.parts.map((part, pi) => {
|
||||
const isLastPart = mi === messages.length - 1 && pi === m.parts.length - 1;
|
||||
// The step boundary where teaching begins (round 8): when
|
||||
// the teach flip happens in a LATER step, its PhaseDivider
|
||||
// replaces this boundary's plain hairline.
|
||||
const teachBoundary =
|
||||
m.role === "assistant" &&
|
||||
mi > 0 &&
|
||||
phases[mi] === "teach" &&
|
||||
phases[mi - 1] !== "teach" &&
|
||||
teachStepIndex(m.parts) === pi;
|
||||
// A tool call that errored BACK TO THE AGENT (validation
|
||||
// failure, malformed args) is invisible work — the agent
|
||||
// reads the error and retries. Owner ruling 2026-09-26:
|
||||
@@ -1302,6 +1323,8 @@ export function Chat({
|
||||
</Reasoning>
|
||||
);
|
||||
case "step-start":
|
||||
if (teachBoundary)
|
||||
return <PhaseDivider key={`teach-step-${pi}`} phase="teach" />;
|
||||
return pi > 0 ? <Separator key={pi} className="my-3" /> : null;
|
||||
case "data-plan-block":
|
||||
// The plan in the chat (wave 4): a frozen snapshot
|
||||
|
||||
Reference in New Issue
Block a user