Skip to content

Restore a single memory change from its journal - #822

Merged
Fei2411 merged 12 commits into
Fei2411:devfrom
klarkxy:feat/464-memory-restore
Nov 2, 2026
Merged

Fei2411 merged 12 commits into
Fei2411:devfrom
klarkxy:feat/464-memory-restore

Conversation

@klarkxy

@klarkxy klarkxy commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator

Issue

Fixes #464

What changed / 改了什么

  • Add the API-only memory-restore endpoint, selecting a journal row by its 1-based line number (plus botId for a private Bot's journal).
  • Apply the inverse of add, forget, and edit operations with exact before/after matching; refuse drifted or duplicate entries, and recreate a removed topic and its index link when needed.
  • Journal the inverse mutation with restored: <original id>, enforce checkSize(), and document the design in docs/plans/2026-11-01-memory-restore.md.

Changelog

A single memory change can now be safely undone from its journal without hand-editing Markdown files.

How I checked it / 怎么验证的

  • npm test (in ds-bot/) — 1,436 passed, 2 skipped; includes restore, redo, drift, topic cleanup, and range errors
  • node scripts/build-client.mjs --check
  • npm run lint — existing warnings only
  • Smoke test — not run: this Windows host has no setsid or DSH checkout; journal writes and recovery are unit-tested
  • Screenshot attached — not applicable: API-only change

Checklist / 检查

  • One issue, one subject.
  • src/client/ changed → npm run build ran and client.js is committed. (No client source changed.)
  • No keys, tokens or personal data, also in screenshots.
  • No AI tool as author or Co-authored-by.

Apply the inverse of a matching add, remove or replace while refusing drifted entries.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 2, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-02T06:37:37.847456Z da6e449 Manual request
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b4240aa6db

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ds-bot/src/host/memory.js Resolved
Comment thread ds-bot/src/host/memory.js Resolved
Comment thread ds-bot/src/host/memory.js Resolved
…topic cap

A restore wrote a line from the change log back verbatim: a value saved as a secret since would return in the clear, a fact remembered again under another topic or new metadata would duplicate, and a removed topic could be rebuilt past the 40-topic cap. The line going back now passes the checks a new entry does, and the scope-wide normalized dedup and topic cap match addEntry.
@klarkxy

klarkxy commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 937a435c16

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ds-bot/src/host/memory.js Resolved
A replace whose before-text was remembered again under another topic or new metadata still restored it beside the new copy. The restore now runs the same scope-wide normalized-text dedup as a remove, skipping only the matched after entry itself — an after that squashes to the before text is no duplicate.
@klarkxy

klarkxy commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9790a1daee

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ds-bot/src/host/memory.js Resolved
A forged remove row with removedTopic and a file like ../../team/MEMORY.md rebuilt its topic at a joined path, writing a forged entry over another scope\u0027s file while inside() still passed — the target stays inside the memory root. Every file a restore names is now checked before anything is built or published: only MEMORY.md or a plain topic file name is a change that can be restored.
@klarkxy

klarkxy commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 46c051c699

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ds-bot/src/host/memory.js Resolved
Comment thread ds-bot/src/host/memory.js Resolved
Comment thread ds-bot/src/host/memory.js Resolved
A filtered split renumbered the rows behind every blank line, so a restore could undo the wrong change; the index now counts physical lines and a blank one is refused. A before-line going back is also held to a single non-empty bullet, so a forged heading or multi-line value cannot corrupt the file or hide entries from recall. And flatFile only checks the name is a flat basename now, so hand-named topic files like Travel.md restore again.
@klarkxy

klarkxy commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 64be9492ed

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ds-bot/src/host/memory.js Resolved
Comment thread ds-bot/src/host/memory.js Resolved
Comment thread ds-bot/src/host/memory.js Resolved
… characters

A change-log row's before line is the whole entry line, metadata included. The secret check ran only on the entry text, so a value that became a saved secret after the row was written could still be put back from the line's metadata, to the file and to the restore's own row. The whole line now goes through secretEntry on both the remove and the replace path.

A file name with a control character passed the flat-name check, and the write it led to failed after the pending record was accepted, leaving every later memory change stuck on a pending record that cannot finish. Flat names now refuse control characters.

The bullet prefix was stripped with ^[-*] while the entry-line check and parseMemory accept an indented bullet, so a before line with leading spaces kept its bullet into the text check and the duplicate check missed a fact already saved; the restore then wrote a duplicate. The same extraction now strips leading whitespace everywhere a row's line becomes text, including the reported text.
@klarkxy

klarkxy commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e0c425f00b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ds-bot/src/host/memory.js Resolved
Comment thread ds-bot/src/host/memory.js Resolved
… a secret name

On a file system that folds case, the file a removed topic's row names can still exist under another case; the case-sensitive lookup missed it and a fresh file written under the row's name replaced it, losing what was saved since. When the named path reports existing, the loaded variant whose name folds to it is used instead, and the change log records the name of the file actually written so a restore of that row finds the line again. A case-sensitive file system keeps the names apart and rebuilds as before.

A removed topic is rebuilt with its name written into the file's heading and the Index link. If the name became a saved secret since the row was written, the restore would put it back in the clear even when the entry itself held nothing sensitive. The rebuild now checks the topic name with the same secretEntry check an entry gets and refuses.
@klarkxy

klarkxy commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c5a6ecb98f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ds-bot/src/host/memory.js Resolved

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c5a6ecb98f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread ds-bot/src/host/memory.js Resolved
Comment thread ds-bot/src/host/memory.js Resolved
… secrets

The temporary name writeText makes beside a file carried the file's whole path, so a legal topic file name near the system's per-name limit made a temporary name over it. The write then failed after the pending record had accepted the change, and every later memory change stopped on a pending record that cannot finish. The temporary name is now a short name in the same folder — a piece of the file's name, the pid, and a uuid — so it stays within the limit however long the file's name is, cannot collide with a parallel write, and still moves over the file in place.

Undoing an add or a replace copies the line the row wrote into the restore's own row as its before, journaled in the clear along with the pending record. When the value on that line became a saved secret since the row was written, the restore put it back into the change log. The whole after-line now faces the same secretEntry check the line going back already did, on both paths.
@klarkxy

klarkxy commented Nov 2, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: da6e449a0a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

The header line kept the summary's update time on a page that is not the
summary; the history page keeps the space empty like the dialog makes it.
@Fei2411
Fei2411 merged commit fe35e83 into Fei2411:dev Nov 2, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants