Repository navigation
Releases: ericwalisko/memware
Releases · ericwalisko/memware
Release list
memware 0.11.0
Upgrade notes
- Your store is tightened to 0600, and the memware home to 0700, on the next command that opens
it. This is automatic and needs nothing from you. Check it withls -la ~/.memware. A
directory you named withMEMWARE_DBorbackup.destis left alone. Windows has no file
modes; see the README's Windows section. memware statshas a new reason under "beliefs left out of injection":instruction. It
counts beliefs that read as an order to the agent rather than a fact. Each stays in the ledger
and in recall; it is only kept out of injection.memware beliefs --stalelists them. A store
that held such a belief before this release shows a non-zero count the first time.- The Claude Code plugin changes with this release (the
SessionEndfix below). Run
claude plugin marketplace update memwareandclaude plugin update memware@memware;
RELEASING.md has the full deploy steps. - The Claude Code plugin's prompt hook no longer passes
-k 6. It reads the newinject.k
setting instead, which defaults to the same 6, so nothing changes unless you set it. The plugin
also ships agardenskill (/memware:garden). - With the relevance filter on, the log trims itself. The first logged prompt after upgrading
strips the prompt and fact text fromrelevance-log.jsonllines older than 30 days and deletes
lines older than 180 (relevance.log_text_days,relevance.log_days). Copy the file first if
you want the old text.
Added
inject.ksets how many beliefs the prompt hook injects per prompt (default 6, 1 to 20).
The Claude Code plugin's hook passed-k 6, so the cap could only change by editing an
installed plugin. The hook now omits-k, andmemware contextreadsinject.kwhen it isn't
given.memware config inject.krefuses anything outside 1 to 20. The Hermes provider keeps
its ownprefetch_k.- A
gardenskill in the Claude Code plugin (/memware:garden) measures and tunes what the
prompt hook injects, then tends the belief ledger. The 0.10.0 calibration was a one-off, and
it only labeled facts memware's own subject rule picked. Nothing checked the facts the relevance
filter adds from lower in the pool, or the candidates it passes over. On one user's 204 prompts
where the filter added a fact, three blind passes labeled 1,781 pairs. The added facts were 35%
relevant, about the same as the picks the filter kept (37%). The picks it dropped were 1%
relevant. With the filter, the block went from 147 relevant facts in 1,224 to 334 in 925.
Facts scored 0.2–0.3 were almost all noise, which is why that ledger's threshold moved to 0.3.
A second cycle measured misses for the first time: of 221 candidates the filter passed over, 8
were relevant.- Measuring:
skills/garden/garden.py(standard library only) reports the filter's health
from its logs: fallbacks, latency, cost, block size and cap-bound prompts. It samples blind
labeling batches, including candidates the filter passed over, so misses are measured too.
It turns two labeling passes, plus a third on their disagreements, into verdicts. - Tuning: the log keeps the filter's score for every candidate in the pool, so past
prompts can be replayed under any threshold,kand pool up to the logged size. The report
searches that grid for the least noise that keeps at least 99% of the relevant facts the
current settings inject. It chooses on older prompts and moves only if the newest cycle's
held-out prompts agree, and then only as far as the smallest step that improves. Several
settings can move in one cycle. On synthetic scores it reaches the optimum in five cycles.
Once nothing else moves, it proposes a pool 10 wider for one cycle when the deepest logged
ranks still hold relevant facts. The timeout rises above a 2% timeout rate. The filter goes
back toshadowwhen it stops beating memware's own picks. - Where it writes: verdicts (pair ids only) and one line of numbers per cycle go to
<home>/labels/garden/, somemware nukeremoves them and the next cycle labels only new
pairs. It never prints a prompt or a fact. The batches that hold them are owner-only and
deleted after scoring. - Gardening the ledger: the skill proposes a fix for each belief shown at least 5 times
and at least 80% noise, such as a sharper subject, a retraction, or keeping it. It reviews
stale, orphaned and contested beliefs, and every fourth cycle it looks for duplicates,
contradictions and subjects that will misfire. It changes nothing without the user's yes.
- Measuring:
python -m memwareruns the CLI, the same entry point as thememwarescript. It used to
fail withNo module named memware.__main__.python -m memware.clistill works.- memware runs on native Windows. CI now runs the whole suite on Windows beside Ubuntu and
macOS, on Python 3.11-3.13, and the README has a Windows section (install, where things live,
known limits). On Windows the capture lock uses
msvcrt.locking, thederiverun lock probes a live process without terminating it, pipes are
read and written as UTF-8, transcript directories match regardless of case, and
derive --provider claude-coderefuses an npmclaude.cmd, because a batch file would pass
transcript text throughcmd.exe; it needs the nativeclaude.exeor--provider openai.
Changed
- The relevance log keeps prompt text for 30 days, not forever. With the relevance filter in
shadoworfiltermode,relevance-log.jsonlgained one line per candidate per prompt, each
with the prompt's text, and nothing ever removed one. One user's log reached 15 MB in six days.
Now, at most once a day, the next logged prompt stripspromptandfactfrom lines older
thanrelevance.log_text_days(30) and deletes lines older thanrelevance.log_days(180),
and a line that will not parse. A stripped line keeps its scores and ids, so labeled pairs can
still be replayed. Both settings take 1 to 3650 days.memware nukeremoves the trim's stamp
file too. memware.cliis now a package with one module per command (memware.cli.recall,
memware.cli.prune, ...). Behaviour,--helptext and thememware = memware.cli:mainentry
point are unchanged;tests/test_cli_help.pypins every command's--helpbyte for byte.
Security
- Hardening from a security review; docs/security.md has the threat model.
- The store, its write-ahead log, snapshots, a restored store, transcript mirror copies,
config.jsonand the review outbox are created 0600. Directories memware creates are 0700.
An existing store is tightened to 0600 on its next open, and the memware home to 0700 when
the store is in it. A directory you named withMEMWARE_DBorbackup.destis left alone. - The injection gate leaves out a belief that reads as an order to the agent rather than a
fact, whoever wrote it.memware deriveno longer files one. Such a belief stays in the
ledger and recall, markedvolatile: "instruction", andmemware statscounts it. Each
injected line is rendered as one line of plain text. - The MCP tools bound their arguments: at most 16 recall phrasings,
kwithin 1–50, a
read_sessionwindow within 0–50, and aremembervalid_fromthat must be a real ISO-8601
time, not in the future. - Keywords longer than 128 characters are left out of search queries.
memware pruneredaction now finds a secret in a belief in its decomposed, fullwidth or
percent-encoded form, or with an invisible character inside it. Its six-character minimum
counts visible characters.
- The store, its write-ahead log, snapshots, a restored store, transcript mirror copies,
Fixed
- The relevance log and usage log are created 0600, like the store. Both were opened with a
plain append and created 0644, so other local accounts could read prompt text whenever the
home directory was not 0700. Each write
now creates the file 0600, and a log written before this release is tightened on its next write. - The staleness gate now leaves out three point-in-time readings it called durable: a count of
cards, tickets, issues or PRs (open card count | 305,blocked cards | 3); a "current" PR,
issue, ticket or card that names the one in flight (current pr | PR #18) or a branch in use;
and the state of a checkout, worktree or clone that reads as a working tree (state | dirty and 8 behind, 39 files modified). Targets, limits, configured states and policies stay durable
(max open cards | 50,feature flag | state | enabled by default).memware beliefs --explain
names the rule that fired. - The plugin's
SessionEndsync now receives the hook payload. It was backgrounded with
nohup … &, and a POSIX shell points a backgrounded command's stdin at/dev/null, so the sync
read{}and printed "nothing to sync"; the session was indexed only by the nextSessionStart
catch-up. The entry now saves the hook's stdin on fd 3 and hands it back to the sync
(exec 3<&0; nohup memware sync … <&3 3<&- … &), which works inshand in Git Bash alike.
memware 0.8.0
Added
- An optional relevance filter for prompt-time injection, off by default. The prompt hook and
the Hermes provider'sprefetchpick beliefs by keyword, so a prompt about an incident report
also got a weekly report's file path. Withmemware config relevance.mode filter, memware asks
TypeSafe's System One model (jev-1.13.0, pinned) one yes/no question per candidate, all in one
request, and injects the candidates at or aboverelevance.threshold, at most k.shadowmakes
the same call, logs each (prompt, candidate) pair torelevance-log.jsonlfor calibration, and
injects whatoffdoes. When it is on, the prompt (up to 2,000 characters) and up to 20
candidate facts go toapi.typesafe.ai, and nothing else does. A task notification, a hook
inside a subagent and a session memware keeps out of its store are never sent. With the filter
off, memware reads no key, opens no socket and prints the same bytes as before. It fails open
on a missing key, a timeout, an HTTP error, a redirect or a malformed reply, with one attempt
under a 1.5 s deadline. With a full pool of 20 candidates the hook took 553 ms p50 and 753 ms
p95, against 84 ms and 99 ms off. It uses the standard library only, with no new dependency.
memware configrefuses a badrelevance.*value and says what switching the filter on sends.
memware nukeremoves the log andrelevance-usage.jsonl.