Partial memory saves and warning recovery
Initially verified on testing in v0.0.24.0. Production promotion: v0.0.30.0.
The main promotion includes the memory recovery behavior and its required fallback/reasoning changes, while preserving main's conversation identity and provider usage bookkeeping. The replay page described below remains available only in testing; it is disabled in production.
Behavior
- Caller attempt one retains its 5,000-character writing target. Attempt two asks for 1,500 characters and approximately 1,500 output tokens, with explicit instructions to rewrite the whole memory and prioritize current facts. This instruction supersedes earlier length guidance, including on semantic fallback and provider-cap compatibility retry.
- The normal provider cap is still 8,192 output tokens; the existing compatibility path for providers that reject that cap remains 4,000. Storage remains 12,000 characters. The smaller targets are prompt guidance, not new rejection thresholds.
- If the second usable result is truncated or oversized, save its available text (up to the existing storage ceiling), mark
memory.warning = "truncated", advance the attempted batch's cursor, reset failures, and use that memory in subsequent chat prompts. This is intentionally lossy behavior authorized by the product owner; the cursor means processed, not a guarantee that every fact survived. - The memory panel displays: “记忆摘要被截断,可能遗漏信息。已保存的内容会正常使用;可重新生成或编辑以补全。”
- Incremental updates retain a known omission warning. A complete manual regeneration or manual edit can clear it; rebuilding from surviving evidence cannot guarantee recovery of all historical omitted details.
- Empty/repetitive output and upstream errors without a usable result remain failures. Only accepted output, including accepted partial output, is billed in the same transaction as the save; BYOK stays exempt from official-credit debits.
- No schema migration: warning metadata lives in the existing memory JSON column.
Repeatable remote testing flow
The dedicated private fixture has no seeded warning. Its setup uses synthetic story data and does not copy a production conversation.
- Sign in to testing with the fixture owner's account. Open the supplied
/api/sessions/<sessionId>/memory/qalink. - Click ① 两次都截断 → 保留并警告. Both simulated model responses have a truncated stop reason. Confirm two attempts, the unchanged actual output cap, saved text, and a warning.
- Open the linked chat, then 记忆与摘要 → 记忆. Confirm the text is present and the yellow warning remains after reloading.
- Click ② 两次都超长 → 保留上限内内容. Confirm the stored text is no longer than 12,000 characters and is visibly marked partial.
- Click ③ 第二次完整 → 清除警告. The first response is truncated; the second completes. Confirm saved text and no truncation warning after refreshing the chat.
The page explicitly uses simulated responses through the actual memory generation/retry/persistence path. It does not call a real model, fabricate provider usage, or debit credits. Each button replaces memory only in this dedicated fixture. Normal regenerate/retry controls still call the configured real provider.
The QA route is available only when the server's Railway environment name is testing, the caller owns the session and its private unpublished world, the world has the explicit QA tag, and the caller has the memory extension. Production deployment configuration and ownership are checked again inside the serialized job. A request header cannot enable QA.
Verification and limits
- Main promotion checks: 48 memory/usage regression tests and four memory-modal layout tests passed; monorepo build (five tasks) and typecheck (eight tasks) passed. The full app suite reported 913 passes and nine pre-existing failures in unrelated navigation, drawer, credit-popup and canvas assertions; their tests and source inputs match the main base exactly. The full server run uses an isolated empty PGlite database: unrelated tests that require a pre-populated schema fail during setup. These broad suites are not claimed as fully green.
- Regression tests first failed on the prior behavior, then passed for retained partial output and stronger prompt guidance.
- Real-updater integration tests cover partial official billing, private-provider boundaries, unchanged output caps, warning persistence, normal prompt injection, all three QA scenarios, production/other-owner denial, and complete-regeneration warning removal.
- Analytics revision:
2026-09-15-retain-partial-memory. Saved results keep outcomeokand includewarninganddegraded; synthetic replay events are labeledsynthetic. A save-rate improvement must not be presented as improved factual completeness. Track degraded saves separately from complete saves and exclude synthetic tests. - This test flow proves application behavior under controlled responses. It does not measure how often a real model follows the smaller writing target or the post-deployment production failure rate.
- The previously identified summary coverage issue is outside this change. This fixture disables story/layered summaries to isolate partial-memory behavior.
See the earlier size recovery investigation for the preceding implementation and historical evidence. Its rejection policy is superseded by this version.
