Skip to content

v0.2.6

Choose a tag to compare

@github-actions github-actions released this 29 Aug 05:15
· 202 commits to master since this release

Every fix in this release is in mem init / mem uninstall. The documented promise for those two
commands is that uninstall reverses exactly what init wrote and leaves everything else alone; five
separate defects broke it, one of them by deleting the user's own text.

Fixed

  • mem uninstall could delete a block of the user's own file -- the per-tool marked block was located with a bare indexOf(start) / indexOf(end) pair, which pairs the first start marker with the first end marker even when they do not belong together. A hand-edit, an interrupted write, or a merge conflict can leave an orphaned <!-- token-goat-mem:<tool>:start --> behind with no end of its own; uninstall then paired that orphan with the end marker of the real block further down and removed every byte in between. In a CLAUDE.md shaped # My notes / orphan / user prose / real block, the user prose went with it. The block is now located by scanning every start marker and taking the first one that resolves to a complete pair, which is how the shared AGENTS.md block has always been located -- the per-tool path simply never got the same rule. A stray end marker sitting ahead of the real block no longer makes install append a second copy, either.
  • A reinstall never upgraded the shared AGENTS.md block's body -- codex, copilot-cli, and copilot-vscode share one reference-counted block, and the writer returned early as soon as the tool was already named in tools=. A body written by an older version of mem was therefore left in place forever: the per-tool blocks were replaced with current text on every reinstall and this one silently drifted away from them. It is now rebuilt from the same constant every time, and returns the file untouched only when the rebuild is byte-identical.
  • mem init rewrote the formatting of files it does not own -- .claude/settings.json was round-tripped through JSON.stringify(parsed, null, 2), so a config indented with four spaces came back indented with two, with its key layout and any non-canonical spacing gone. .vscode/tasks.json and keybindings.json went through jsonc-parser's modify with a formattingOptions, which reformats the entire containing array, so a hand-written one-line { "key": "ctrl+q", "command": "noop" } came back exploded across five lines. Neither file is mem's to restyle. Both paths now edit text rather than reserialize an object: modify with no formatting options yields a genuinely surgical edit that touches nothing else, and mem re-renders only its own inserted payload, at the document's own indent unit (tabs included) and line ending. Comments and trailing commas survive in both directions.
  • mem uninstall left behind the containers mem init had created -- installing into a settings.json with no hooks at all, which is the common case, created hooks and hooks.SessionStart; uninstall removed the hook group and stopped, leaving a "hooks": { "SessionStart": [] } husk. tasks.json had the same shape via "inputs": []. Uninstall now prunes an array or object that its own removals emptied. An empty hook array is inert, so pruning one a user happened to have written by hand costs them nothing.
  • mem init wrote LF into files authored with CRLF, and mem uninstall grew a blank line each time -- the marked block was assembled with hard-coded \n, so installing into a CRLF-authored CLAUDE.md produced a file with mixed line endings, and rewriting the shared block's tools= line dropped the \r from it. Uninstall then looked for a literal "\n\n" separator it would never find in such a file and left the surrounding blank lines in place, so each install/uninstall cycle added one. Every write now detects and preserves the file's own line ending, and the separator inserted by install is exactly the one removed by uninstall -- so a file with no trailing newline no longer gains one, and a whitespace-only file is no longer emptied.
  • The repository's own tracked files can no longer be checked out as CRLF -- a .gitattributes with * text=auto eol=lf pins them. Under core.autocrlf=true, which is the Windows default, docs/integrations/copilot-vscode.md arrived with CRLF on all 161 lines, and the doc/code consistency test added in 0.2.5 parses that file with a /```json\n/ regex that cannot match \r\n. That is a test that fails for a reason having nothing to do with what it tests, on a checkout that is otherwise correct.
  • The dry run described a shared-block install it was no longer doing -- now that a reinstall refreshes a stale body, a tool already named in tools= can have work to do, and mem init --dry-run still reported it as "install would join existing shared block (adds <tool> to tools=)". That case now says it would refresh the body.
  • The npm audit note in CONTRIBUTING.md described advisories that no longer exist -- it documented five dev-only advisories in the esbuild/vite/vitest chain and the reasoning for not forcing the fix. The toolchain upgrade that cleared all five landed before 0.2.5; npm audit has reported zero since, and the paragraph telling contributors otherwise outlived it.

Added

  • Nine regression tests that assert on file bytes, not parsed structure -- the formatting damage above was invisible to the existing suite because every assertion went through JSON.parse, and the round-trip leaks were worse than invisible: two tests had encoded the leftover empty containers as the expected result, one of them inside a test named "uninstall returns the file to its pre-install state". The new tests seed hand-formatted fixtures -- four-space, tab-indented, single-line, comment-carrying, CRLF -- and compare the file to itself after an install/uninstall cycle. Five were verified failing against the previous implementation before the fix landed.
  • Three regression tests for malformed and stale markers -- an orphaned start marker ahead of a real block, a stray end marker before one, and a shared block whose body was written by an older version. Each was verified failing first.
  • A ## Line endings section in CONTRIBUTING.md -- explains what .gitattributes pins, when to run git add --renormalize ., and the distinction that matters here: files mem edits are the user's, and code that writes them must never hard-code \n.