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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ All notable changes to MeMesh are documented here.
- 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).
- 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).
- `memesh kg rename-project --from X --to X` (the same name twice) is refused. Before, `--apply` counted every memory of X as a merge and removed its only project tag (#519).
- `kg rename-project --apply` writes its backup to `backups/` beside the database instead of `./data/backups/` under whatever directory it was run from, and the backup now includes changes still in the database's write-ahead log; the printed restore command uses `sqlite3 .restore` and is quoted for any path. The dry run prints how many message rows would be left in place, and an apply that cannot write no longer reports every row as left in place. Listing and the dry run open the database read-only, so they no longer trigger the automatic confidence decay or any other write; the counts they print now match `--apply`, including when the database still needs a unique index that `--apply` creates, and the "moved" count no longer includes the rows left in place. Giving only one of `--from`/`--to`, an invalid `--to`, or the same name twice prints one error line and exits 1 before the database is opened, even with `--apply`. Listing and the dry run also no longer create a database: with none present, listing prints "No MeMesh database yet" (exit 0, `[]` with `--json`), and a dry run with `--from`/`--to` exits 1 saying there is no database at that path. Before, both created an empty database and printed "No project:* tags found." `--apply` with neither `--from` nor `--to` is refused instead of listing through a writable open. The dry run now runs the real rename on a temporary copy of the database instead of estimating collisions, so its counts match `--apply` for any index, trigger or pending migration the database has; and `--apply` reads back, inside its transaction, every renamed tag (the old tag gone, the new one present) and every moved message row (scoped to the new project), and rolls back with one error line if any is not where it should be, for example because a trigger ignored or undid the change. Before, the memory could keep `project:old` while its messages moved. A message row counts as left in place only when the destination project really holds a row with the same unique key; any other failure, including an error a trigger raises or a collision a trigger's own write hits, rolls the rename back instead of being reported as a success. The dry run's temporary copy is deleted when it finishes; an interrupted preview (Ctrl-C, kill) can leave it in the temp folder, owner-only. A database whose `-wal` file is empty can now be listed and previewed from a read-only directory, and a preview that cannot write its temporary copy names the temp folder and the cause. On a read-only directory, listing and the dry run read the database as immutable when no write-ahead log, or only an empty one, is present (a non-empty log next to the real file, also through a symlink, is refused with one line), and any failure while listing is one error line, not a stack trace.

## [4.10.11] — 2026-09-29

Expand Down
5 changes: 4 additions & 1 deletion dist/core/project-tags.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { MemeshDatabase } from '../storage/sqlite.js';
import { MemeshDatabase } from '../storage/sqlite.js';
export interface ProjectTagCount {
project: string;
count: number;
Expand All @@ -15,8 +15,11 @@ export interface RenameProjectResult {
messageRowsBlocked: number;
}
export declare function listProjectTags(db?: MemeshDatabase): ProjectTagCount[];
export declare function sameProjectRefusal(from: string, to: string): string | null;
export declare function renameProjectTag(from: string, to: string, opts?: {
apply?: boolean;
db?: MemeshDatabase;
}): RenameProjectResult;
export declare function hasRenameWork(from: string, db?: MemeshDatabase): boolean;
export declare function openReadOnlyForPreview(dbPath: string, openHandle?: (target: string) => MemeshDatabase): MemeshDatabase;
//# sourceMappingURL=project-tags.d.ts.map
2 changes: 1 addition & 1 deletion dist/core/project-tags.d.ts.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

155 changes: 133 additions & 22 deletions dist/core/project-tags.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading