mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 02:01:10 +02:00
User test surfaced the actual auto-title bug: the entire pipeline
(enqueue → process → watcher) works correctly, but the task result
itself is empty:
[memoro] enqueued title task { taskId, memoId }
[memoro-llm-watcher] saw 1 done title task(s)
[memoro-llm-watcher] writing title to memo XXX: ""
[memoro-llm-watcher] applied + cleared row YYY
The watcher faithfully wrote "" to memo.title, the input placeholder
showed "Titel..." again, and we looked stuck. Three layered fixes so
this can't bite us in any execution path going forward.
1. generate-title.ts: extract rules logic + use it as runLlm fallback
Pulled the deterministic first-sentence heuristic into a private
`rulesImpl()` function so both `runLlm` and `runRules` can call
it. runLlm now invokes rulesImpl as a fallback when the cleaned
LLM output is empty. This catches the case where the model emits
only punctuation, only special tokens, or only whitespace — all
of which collapse to "" after my cleanup chain (`.trim()` → strip
surrounding quotes/markdown → strip trailing dots → `.trim()`).
The most likely real-world trigger: Gemma 4 occasionally emits a
single `.` for short prompts that hit its over-strict
"answer with ONLY the title" instruction. The cleanup turns
"." into "" and we lose the result.
2. llm-watcher.svelte.ts: date-based backstop for any empty result
Belt-and-suspenders: even if a future task implementation forgets
the rules fallback, the watcher itself now guarantees a non-empty
title. When `row.result.trim()` is empty, synthesize a label like
"Memo vom 9. April 2026" from the memo's createdAt (or the
current date if createdAt is also broken). The user always sees a
real title — never an empty placeholder.
Same write path otherwise (encryptRecord + memoTable.update +
delete queue row), just with the guaranteed-non-empty value.
3. llm-watcher.svelte.ts: enhanced diagnostic logging
The "writing title" log now includes `row.source` (which tier
actually executed) and `row.attempts`, so the next time we see
weird behavior we can tell at a glance whether it was the
browser tier, the rules tier, or the server. The empty-result
path logs `console.warn` (not info) with the raw result via
JSON.stringify so we see exactly what came back ("", ".", " ",
undefined-coerced-to-string, etc.).
After this commit lands:
- Tier 0 user: runRules returns at minimum "Ohne Titel" (its
own fallback). The watcher writes that.
- Browser tier with empty Gemma output: runLlm now falls through
to rulesImpl which also can't return empty. The watcher writes
the rules-tier output.
- Any other freak case where the result is still empty: the
watcher's date-based backstop kicks in. "Memo vom <date>".
So the user-visible "stuck on empty title" symptom is impossible in
all three layers.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| .. | ||
| api | ||
| calc/packages/shared | ||
| calendar | ||
| cards | ||
| chat | ||
| citycorners | ||
| contacts | ||
| context | ||
| docs | ||
| guides | ||
| inventar | ||
| mana | ||
| manavoxel | ||
| memoro | ||
| moodlit | ||
| mukke | ||
| news | ||
| nutriphi | ||
| photos | ||
| picture | ||
| planta | ||
| presi | ||
| questions | ||
| skilltree | ||
| storage | ||
| times | ||
| todo | ||
| traces | ||
| uload | ||
| zitare/packages/content | ||