Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,9 @@ host is recallable from all of them. Not installed yet? Follow
general lesson). `recall` searches the bound project (or `project`), memories
with no project and global ones, and says which in `scope`. When you tag by hand (the CLI, or another
project), use `project:<id>`, where `<id>` is the `project` field of the
`briefing` result (CLI: `memesh briefing --json`). The injected block shows
only the readable name. `remember` stores a plain-name tag for the call's
`briefing` result (CLI: `memesh briefing --json`). The first line of the
injected block gives this session's exact project id (readable name plus a
short hash); the memories below it show only the readable name. `remember` stores a plain-name tag for the call's
own project as the id (and says so in `retagged`), but a plain name for any
other project, or on a memory already filed under it, stays a different
scope that this project's sessions never see.
Expand Down Expand Up @@ -208,7 +209,7 @@ Under Claude Code with the MeMesh plugin, hooks capture automatically:
- **SessionStart** injects the work topology (the same memory block
`briefing` returns, with an eligible exact-project handoff ahead of ranked memories after optional repository facts, plus a work-package notice at `full` that `briefing`
never includes) at the top of the session, whenever the configured level
has something to show; an empty project at `minimal` injects nothing.
has something to show; an empty project at `minimal` injects only the project line.
- **PreToolUse (Edit|Write)** surfaces memories related to the file being
edited.
- **PostToolUse (Bash)** records git commits with diff stats.
Expand Down
6 changes: 4 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ All notable changes to MeMesh are documented here.

- The dashboard's Project page loads the selected project's memories a page at a time ("Load older memories") instead of the newest 2000 of the whole library, so a project whose memories are older than that no longer reads as empty while its chip counts them. `GET /v1/entities` takes `project` — decided by the rule `GET /v1/projects` counts with (the `project:` tag, else a `lesson-<project>-<pattern>` name of a project at least two characters long; the project's session handoff is not one of its memories) — and `offset`; the Memories filter chips use the same rule. Switching project no longer shows the previous project's memories if the new project's first page fails to load, "Load older memories" keeps keyboard focus while it loads, and the notice beside it counts the memories the list shows.
- Dashboard Home: a rate-limited server no longer tells you to reload and run `memesh doctor`; the next-step card no longer claims to have checked the search index, and shows "unavailable" instead of "checking" forever when the server's health request fails; the memory-loop percentage compares the last seven days with the seven days before them (it compared the last seven days that had activity); the timeline chart fills its card, clears when the data is removed and spaces its bars by day; an empty library no longer scores a health of 0; and accepting a compaction proposal says how many source memories it archived.
- `npm run audit:memory` reports a memory whose `replaced_history` is not a list, holds more than 50 versions or is larger than 256 KiB, and exits 2 when a file is not a database or cannot be queried, instead of printing a clean verdict.
- Dashboard: "Check now" in Settings shows an error when the re-check fails, instead of leaving the old "Up to date" line as if it had worked; a cross-origin refusal (`auth.cross-origin`) no longer says it needs a Terminal, and asks you to open the address `memesh serve` printed; missing and wrong translations are fixed in all 11 languages.
- Dashboard doctor banner: it no longer tells you to run `memesh doctor --verbose` (the option does not exist) in place of the server's own advice; the repair button waits up to 150 s (the server's 120 s budget for a plugin-cache refresh, plus 30 s for its two doctor runs, before and after the repair; a margin, not a measured time) instead of giving up after 10 s, and when the first of the two Codex commands leaves under 5 s of that budget the second is not started: the repair stops with a message that the marketplace upgrade ran and to run `codex plugin add memesh@pcircle-memesh` yourself, in `memesh doctor --fix` and, in your language, in the dashboard (`POST /v1/doctor/fix` answers it with the new error code `doctor.repair-incomplete`); a failed check is listed before warnings; a copy that cannot work (no clipboard on a non-secure address) says so; and a failed refresh keeps the banner instead of making a broken install look fixed. The feedback form disables its button until there is text, and notes in the issue when system info or diagnostics could not be attached.
- Dashboard: SVG icons and charts use real attribute names (`stroke-width`, not `strokeWidth`, which browsers ignore), a roadmap's "low-signal hidden" count counts only what the signal gate removed, a project with memories no longer reads "No memories" in the mindmap, the roadmap's month and week labels no longer land in the wrong month or week west of UTC, a phase chip clicked in the mindmap view now takes you to that phase in the tree, the roadmap shows one column instead of a 280-pixel side column on a narrow screen, and the phase strip marks the latest phase current only while it is still open (as the tree already did for "active"), the insights banner's × works from the keyboard (its two buttons are now side by side, not one inside the other), `?tab=constructor` no longer blanks the page, the empty library's command-line reference no longer shows a Reset-demo button that had nothing to reset, a demo reset whose result cannot be read back says that, instead of saying the server is unreachable, a compaction proposal whose stored content cannot be read offers Reject only, and the Analytics age table lists every memory type (it dropped any type outside a fixed list of 13).
- A host that stalled past its router lease (a laptop that slept, for example) now registers again when the router answers one of its requests (a heartbeat, for example) with `stale_generation`, waiting longer each time the router keeps doing so. Before, it stayed connected and silent: the router no longer listed it or delivered to it, and nothing was reported.
Expand Down Expand Up @@ -59,10 +61,10 @@ All notable changes to MeMesh are documented here.
- `memesh-host-acp` no longer keeps running and exits 0 with no output after its agent process dies. It now unregisters, prints why the agent stopped (exit code or signal) and exits 1. A normal shutdown is not reported as a failure (#532).
- A message an agent host finished after the router had stopped waiting for it (for example a long ACP prompt) is no longer sent to that host again when its session registers anew. The router now records the late acceptance for exactly the attempt that timed out, on the same current connection, and `message receipts` then shows that acceptance; the timed-out attempt stays recorded in the database. A host that stops before it can send its acceptance can still receive the message again (#532).
- Under Codex, a message sent to a principal that spans several threads is reminded again in the principal's next thread when the router had queued it into a different thread that ended without running it. Before, the host acceptance of that other thread kept it quiet everywhere, so the principal never learned of it. The thread it was queued into is reminded too once the MeMesh host connection that accepted the message has ended. This matters for acceptances that carried the body: ones recorded before the queue switched to notices (for example a `codex exec` run that exited before running the message), and the app-server host's. A notice-only acceptance never silenced the reminder (#514).
- A message router started before an upgrade no longer keeps routing with the old code unnoticed. The router now reports its MeMesh version when a session connects. An older router from this release on steps aside and the installed one starts. A router from 4.10.11 or earlier is refused with the command to stop it (`pkill -f dist/host-runtime/router.js`), and the Claude Code and Codex hosts print that reason instead of a bare "registration failed". A session send that falls back to its principal now also tells the sender when the intended session is not connected, since only that session can take the message in. A Codex companion record left by an older MeMesh no longer blocks the next session start: companions now use a control socket name the older one never bound, and leave its file in place. A companion killed while it connects to the router leaves a record the next start clears. When a socket that no record accounts for is in the way, or another start for the same session is still under way, the session start prints one `companion_busy` line that names the cause and leaves the file alone, instead of a bare failure: nothing can prove such a socket unused. A stopping companion no longer removes a socket another companion has since bound at the same path, and a companion that cannot stop cleanly writes why to `codex-companion.log` in the MeMesh data directory (#518).
- A message router started before an upgrade no longer keeps routing with the old code unnoticed. The router now reports its MeMesh version when a session connects. An older router from this release on steps aside and the installed one starts. A router from 4.10.11 or earlier is refused with the command to stop it (`pkill -f dist/host-runtime/router.js`), and the Claude Code and Codex hosts print that reason instead of a bare "registration failed". A session send that falls back to its principal now also tells the sender when the intended session is not connected, since only that session can take the message in. A Codex companion record left by an older MeMesh no longer blocks the next session start: companions now use a control socket name the older one never bound, and leave its file in place. A companion killed while it connects to the router leaves a record the next start clears. When a socket that no record accounts for is in the way, or another start for the same session is still under way, the session start prints one `companion_busy` line that names the cause and leaves the file alone, instead of a bare failure: nothing can prove such a socket unused. A stopping companion no longer removes a socket another companion has since bound at the same path, and a companion that cannot stop cleanly writes why to `codex-companion.log` in the MeMesh data directory. A session end that fails now says "session end failed" instead of "registration failed".
- A small database last opened by an older release (before 4.2.11, or with Thai, Lao, Khmer, half-width katakana or rare CJK characters indexed by an older build) opens again after upgrading. Before, every open failed with "database disk image is malformed" although the database was not damaged, because an upgrade step removed keyword-index rows using the new text splitting before the index was rebuilt (#522).
- Memories about a file are shown before an edit in every session again. Once any session (or another agent on the same machine) had been shown them, every other session editing that file got nothing, and the hook record said "nothing to recall". Each session now keeps its own list (a subagent keeps one of its own), a repeat is recorded as throttled, and a list that cannot be written or cleaned up is recorded as an error instead of failing silently (#521).
- Importing with `overwrite` (MCP `import`, `POST /v1/import`, `memesh import --merge overwrite`) now keeps the memory's previous observations, tags and title in its `replaced_history`, the same way `remember` with `replace: true` does. Before, the old content was erased with no way back. Importing a file that names one memory more than once is refused before anything is written (#530).
- Importing with `overwrite` (MCP `import`, `POST /v1/import`, `memesh import --merge overwrite`) now keeps the memory's previous observations, tags and title in its `replaced_history`, the same way `remember` with `replace: true` does. Before, the old content was erased with no way back. Importing a file that names one memory more than once is refused before anything is written. An overwrite whose content is identical to what the memory holds (same title, observations in the same order, and tags) records no history entry, so restoring the same backup again no longer pushes real earlier versions out of `replaced_history`.
- A project name is now stored and looked up exactly as written (no trimming, no Unicode normalising), and an empty project or one written as a path (`/Users/me/proj`, `C:\proj`, `a/b`, `./foo`, `../foo`, `~/foo`) is refused with an error naming the field by `learn`, `task_state` and `briefing` (MCP), `POST /v1/learn`, `memesh learn`, `memesh task`, `memesh briefing` and `memesh import --notes`; a bare name such as `.ssh` is still accepted. `POST /v1/learn` now requires `project` and answers 400, storing nothing, when it is missing, instead of filing the lesson under the directory `memesh serve` was started in; `memesh learn` takes `--project` (without it, the working directory's project, as before). `GET /v1/task-state` and `GET /v1/briefing-index` read a project key exactly as sent, so a path-shaped key stored by an older version stays readable; they refuse a blank or over-long one. Messaging and `kg rename-project` project rules are unchanged, and memories already stored under a path-shaped project tag are left as they are. The PreCompact hook no longer uses its own working directory when the payload has no usable `cwd`, and no longer writes payloads without a usable `session_id` into one shared `pre-compact-unknown` memory: a missing, blank or non-text `cwd` or `session_id` makes it skip and record the reason (#527).
- A message sent through the MCP `message` tool keeps every `null` in its JSON payload. Before, the MCP boundary removed each null-valued key at any depth of the payload while `send` still reported success, so the recipient got different data than the CLI or HTTP would have stored (#517). A null-valued top-level tool parameter still means "left blank", except `payload`, whose null is a value (#553).
- The MCP `message` tool accepts `payload: null` on `send`, as its schema and the HTTP API already did; it was refused with `payload: Invalid input` (#553).
Expand Down
6 changes: 4 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,10 @@ expressed as `maxWorkers: 1` + `fileParallelism: false`; the older
`singleFork`/`maxForks`/`minForks` keys do not exist in Vitest 4 and were being
silently ignored.

`npm run typecheck` uses `tsconfig.check.json`, which covers `src/`, `tests/`
and the root config files. `tsconfig.json` is narrower on purpose — it is the
`npm run typecheck` runs two configs: `tsconfig.check.json` (`src/`, `.ts`
tests outside `tests/dashboard/`, root `*.config.ts`) and
`tsconfig.check-dashboard.json` (`dashboard/src/`, `.tsx` tests and the
dashboard's `.ts` tests). `tsconfig.json` is narrower on purpose — it is the
config that emits `dist/`.

### Coverage, and what a 0% file means
Expand Down
Loading
Loading