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:
amosblomqvist
2026-10-05 06:08:51 +03:00
parent 6b58d87d9e
commit 450e0f78f0
5 changed files with 155 additions and 26 deletions
+14 -7
View File
@@ -1574,13 +1574,18 @@ describe("stale-job recovery sweep (liveness-gated)", () => {
// alone must NOT trigger recovery anymore.
jobStore.updateJob(jobId, { updatedAt: new Date(Date.now() - 30 * 60_000).toISOString() });
registerJobAbort(jobId, new AbortController()); // a loop is executing
let respawned = 0;
setJobRespawn(() => {
respawned++;
// JURISDICTIONAL (owner round 8, 2026-10-05): the sweep scans the
// SHARED jobs dir — under the full suite, OTHER FILES' processes
// legitimately leave running records this sweep may respawn. Only
// THIS test's job is this test's business: collect ids, assert ours
// never respawns (the counter form saw foreign respawns as failures).
const respawnedIds: string[] = [];
setJobRespawn((id) => {
respawnedIds.push(id);
});
resetSweepThrottle();
recoverStaleJobs();
assert.equal(respawned, 0, "a live loop is provably executing — no respawn beside it");
assert.ok(!respawnedIds.includes(jobId), "a live loop is provably executing — no respawn beside it");
assert.equal(jobStore.getJob(jobId)!.activity, "starting", "the record is untouched");
// Hermetic teardown: settle + unregister so later sweeps in THIS suite
// never see this fixture as a fresh orphan.
@@ -1590,13 +1595,15 @@ describe("stale-job recovery sweep (liveness-gated)", () => {
it("a running record WITHOUT a registration is an orphan: the loop is re-spawned immediately (no age wait)", () => {
const { jobId } = orphanJob();
let respawned: string | null = null;
// JURISDICTIONAL (see above): foreign respawns may interleave under
// the full suite — ours must be among them, at once.
const respawnedIds: string[] = [];
setJobRespawn((id) => {
respawned = id;
respawnedIds.push(id);
});
resetSweepThrottle();
recoverStaleJobs();
assert.equal(respawned, jobId, "the orphan's loop is re-spawned at once");
assert.ok(respawnedIds.includes(jobId), "the orphan's loop is re-spawned at once");
assert.equal(jobStore.getJob(jobId)!.activity, "recovering: re-running");
// Hermetic teardown (see above) — the respawned loop is the TEST's
// fake seam, nothing real runs.