- Dropped the terminal split artifact so repeated saves no longer grow a
blank line per write.
- Replaced the partition-and-concat merge with an ordered line list:
headings, prose, and footers keep their positions; new lessons insert
at the head of the first bullet run and the cap trims oldest bullets.
- Strengthened tests to byte-exact idempotence and mixed-Markdown order.
- Review follow-up for PR #6774.
Use the pre-session memory prompt snapshot as the learned.md baseline when startup consolidation refreshes before a session-scoped cache exists. This keeps active-session learn writes out of the refreshed prompt while still surfacing the new consolidated summary.
Refs #3743
Refresh the startup consolidation summary without rereading learned.md for the active session, so lessons captured while startup is still running remain deferred to the next session.
Refs #3743
Background memory startup writes memory_summary.md after the initial system-prompt build has already cached an empty value for the session. Drop the cached snapshot before refreshBaseSystemPrompt so the active session actually picks up the freshly consolidated summary instead of returning the stale cached one.
Refs #3743
Stopped passive autolearn from adding hidden conversation messages and froze local memory developer instructions per session so learn writes land in future sessions instead of mutating the active Anthropic prompt prefix.
Fixes#3743
Migrate 203 test files (356 call sites) from fs.rm/fs.rmSync to
removeWithRetries/removeSyncWithRetries to reduce EBUSY test failures
on Windows. removeWithRetries is now exported from @oh-my-pi/pi-utils.
The migration uses a regex-based approach that:
- Replaces fs.rm(path, { recursive, force }) → removeWithRetries(path)
- Replaces fs.rmSync(path, { recursive, force }) → removeSyncWithRetries(path)
- Replaces fs.rm(path) → removeWithRetries(path) (no options)
- Skips fs.rm/fs.rmSync inside template literals (bun --eval scripts)
- Adds imports to existing @oh-my-pi/pi-utils import or creates new one
- Removes unused fs imports where fs.rm was the only fs usage (4 files)
Grill test-gap finding: the learned-lesson read-back had no coverage for the
budget clamp when a memory summary already fills `summaryInjectionTokenLimit`.
Add a case with an oversized summary asserting the lesson is dropped and the
combined block stays bounded.
The `learn` tool previously required a `hindsight`/`mnemopi` backend. It now
also works when `memory.backend` is `local` (the file-based rollout backend):
lessons append to a `learned.md` under the project's memory root, kept separate
from the consolidation artifacts so a consolidation pass never clobbers them,
and are injected into future sessions alongside the memory summary.
- memories: `saveLearnedLesson` (newest-first, deduped, count- and per-field
size-capped, secret-redacted, injection-neutralized) with per-path write
serialization; `buildMemoryToolDeveloperInstructions` reads `learned.md` and
shares one injection budget with the summary; `redactSecrets` extended with
GitHub/npm/Slack/Google token prefixes.
- local backend: implements `save()`; status reports `writable: true`.
- learn tool: `local` execute branch; `createIf`/`isToolAllowed`/auto-include
and the standing guidance extended to `local`; local saves tier as a `write`
approval.
- read-path prompt: renders the learned-lessons block when present.
- Lessons are injection-neutralized and secret-redacted on BOTH write and read
(they render unescaped into the system prompt).
Also moves the auto-learn CHANGELOG entry out of the released [15.12.6] section
(a cherry-pick artifact) back under [Unreleased] and notes the local backend.
Tests: local storage (format, dedup, cap, redaction incl. provider/delimiter-
split tokens, concurrency), read-back (with/without summary, off-gating, raw
hand-edited file), tool gating + write-approval tiering.