memoir-cli 3.12.0 → 3.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +128 -137
  2. package/bin/memoir-work.js +9 -0
  3. package/bin/memoir.js +50 -8
  4. package/docs/AUDIT-REMEDIATION.md +55 -0
  5. package/docs/CASE_TAPE_AMNESIA.md +39 -0
  6. package/docs/HANDOFF-SECURITY-AUDIT.md +106 -0
  7. package/docs/LOCAL-HANDOFF-VALIDATION.md +129 -0
  8. package/docs/MCP-V2-MIGRATION.md +17 -0
  9. package/docs/PROJECT-HANDOFF.md +301 -0
  10. package/docs/PROJECT-MAP-TRIAL.md +149 -0
  11. package/docs/PROJECT-VIEW-DEBUG.md +66 -0
  12. package/docs/PROJECT-VIEW-VALIDATION.md +136 -0
  13. package/docs/RELEASE-3.14-VALIDATION.md +36 -0
  14. package/docs/RELIABILITY-ROLLOUT.md +57 -0
  15. package/docs/RETRIEVAL-INDEX.md +45 -0
  16. package/docs/RETRIEVAL-RESULTS.md +26 -0
  17. package/docs/SPEC.md +684 -0
  18. package/evals/CONTINUITY-PROTOCOL.md +45 -0
  19. package/evals/cases.json +200 -0
  20. package/evals/results/retrieval-2026-09-05.json +5333 -0
  21. package/evals/retrieval-performance.mjs +99 -0
  22. package/evals/run.mjs +87 -0
  23. package/package.json +13 -5
  24. package/src/adapters/index.js +13 -6
  25. package/src/adapters/restore.js +83 -36
  26. package/src/cloud/storage.js +130 -93
  27. package/src/commands/activate.js +18 -7
  28. package/src/commands/cloud.js +55 -4
  29. package/src/commands/consolidate.js +49 -10
  30. package/src/commands/diff.js +2 -2
  31. package/src/commands/doctor.js +3 -3
  32. package/src/commands/push.js +156 -161
  33. package/src/commands/recall.js +1 -1
  34. package/src/commands/restore.js +32 -44
  35. package/src/commands/resume.js +15 -164
  36. package/src/commands/session.js +51 -9
  37. package/src/commands/snapshot.js +6 -7
  38. package/src/commands/status.js +23 -1
  39. package/src/commands/upgrade.js +11 -9
  40. package/src/commands/validate.js +3 -0
  41. package/src/commands/view.js +2 -2
  42. package/src/commands/why.js +4 -3
  43. package/src/config.js +9 -40
  44. package/src/context/capture.js +126 -32
  45. package/src/context/handoffs.js +72 -0
  46. package/src/events/summary.js +122 -0
  47. package/src/integrations/setup.js +88 -0
  48. package/src/mcp.js +105 -152
  49. package/src/memory/lexical-index.js +65 -0
  50. package/src/memory/repository.js +16 -0
  51. package/src/memory/scope.js +65 -0
  52. package/src/memory/search.js +165 -70
  53. package/src/memory/store.js +141 -0
  54. package/src/providers/index.js +182 -51
  55. package/src/providers/restore.js +5 -1
  56. package/src/security/encryption.js +34 -60
  57. package/src/security/files.js +155 -0
  58. package/src/session/brief.js +47 -0
  59. package/src/session/inject.js +12 -6
  60. package/src/session/lock.js +39 -118
  61. package/src/session/migrations.js +6 -0
  62. package/src/session/render.js +34 -4
  63. package/src/session/state.js +200 -33
  64. package/src/work/cli.js +64 -0
  65. package/src/work/errors.js +8 -0
  66. package/src/work/server.js +28 -0
  67. package/src/work/setup.js +96 -0
  68. package/src/work/store.js +340 -0
  69. package/src/work/ui/app.js +398 -0
  70. package/src/work/ui/index.html +45 -0
  71. package/src/work/ui/style.css +248 -0
  72. package/src/work/view.js +93 -0
  73. package/src/workspace/tracker.js +84 -332
  74. package/supabase/migrations/202609050001_backup_versions.sql +50 -0
@@ -0,0 +1,106 @@
1
+ # Project handoff adversarial audit — 2026-09-06
2
+
3
+ **Status: local preview, not a public deployment or a security-certified product.**
4
+ The original functional tests were not a dedicated adversarial audit. This
5
+ follow-up exercised the new project handoff, its MCP interface, CLI, settings
6
+ writer, ledger parser and Git metadata helper using synthetic attack fixtures.
7
+ It found real gaps and changed the implementation. All changes remain local.
8
+
9
+ ## Findings and fixes
10
+
11
+ | Finding | Impact | Fix |
12
+ |---|---|---|
13
+ | MCP check tool accepted arbitrary host commands | A memory-tool call could read server environment values and write outside the project using server privileges | Disabled command execution over MCP completely. Existing tool name returns a refusal. Checks use the CLI under the coding client's ordinary terminal permissions |
14
+ | Reading Git status executed a configured fsmonitor hook | A resume operation could execute repository-controlled code | Removed dirty-status execution from the shared repository metadata helper. Dirty status is now unknown; per-file freshness still works |
15
+ | JSON serialization hid some secrets from the scanner | Field-leading environment assignments and embedded JSON credentials could be saved | Scan decoded strings, normalize common invisible obfuscation for detection, and reject recognized credentials before storage |
16
+ | Rendered record data could create Markdown structure and image links | A stored answer could imitate a new evidence section or contain active image markup | Escape rendered fields and keep them on one line; explicitly label all stored text untrusted |
17
+ | A file named `__proto__` disappeared from input evidence | Changes to a declared file could fail to invalidate a check | Use dictionaries without an object prototype and validate original input maps without schema normalization dropping that key |
18
+ | Maximum-size check input lists broke subsequent reads | 100 explicit inputs plus automatic manifests created a ledger the old reader rejected | Validate the combined maximum consistently |
19
+ | Incomplete receipt/history validation | Incorrectly typed evidence, reordered history and malformed retractions could be accepted | Strict receipt, metadata, revision-order and history-completeness validation; preserve and refuse malformed data |
20
+ | Non-object Cursor settings could be rewritten | Setup could replace an unexpected existing configuration shape | Reject before any planned settings/instruction edits are applied |
21
+ | Unbounded CLI stdin | Oversized input was buffered and parsed | Enforce a 16 KiB limit while reading and before parsing |
22
+
23
+ Additional hardening sanitizes parser and filesystem errors so damaged-file
24
+ contents are not returned to an MCP client. Unsafe controls and direction
25
+ overrides are rejected after decoding. The memory interface remains local stdio.
26
+ The later project-view feature adds an opt-in HTTP listener bound only to
27
+ 127.0.0.1, with a per-process capability, strict Host/Origin validation and no
28
+ command execution. It adds no telemetry, cloud upload or background daemon.
29
+ See [the project-view validation](PROJECT-VIEW-VALIDATION.md) for its separate
30
+ browser and request-security checks. The counts below describe the earlier audit.
31
+
32
+ ## Adversarial evidence
33
+
34
+ `test-work-adversarial.mjs` contains **19 scenarios**. The first baseline had
35
+ 14 failed assertions. Further probing then reproduced execution of a synthetic
36
+ Git fsmonitor hook and caught a normalization issue in the first prototype-key
37
+ fix. These are regression probes, not 14 independent vulnerability ratings.
38
+ No real credentials, personal home files or external attack targets were used.
39
+
40
+ The final suite passes all 19 assertions. Eighteen scenarios verify defenses;
41
+ one deliberately demonstrates the remaining valid-receipt-tampering boundary
42
+ and verifies that it is explicitly disclosed. A passing test count must not be
43
+ interpreted as proof that every attack is blocked.
44
+
45
+ Covered attacks include host command/environment access through MCP, Git-hook
46
+ execution during resume, damaged-file error leakage, multiple secret formats,
47
+ invisible and directional text, Markdown spoofing, special dictionary keys,
48
+ input limits, malformed and reordered history, configuration clobbering,
49
+ oversized stdin, symlink escape, shell metacharacters and personal-scope requests.
50
+
51
+ Run the dedicated suite with:
52
+
53
+ ```sh
54
+ node test-work-adversarial.mjs
55
+ ```
56
+
57
+ `npm test` includes it alongside the existing functional suites. The dependency
58
+ audit against the npm advisory data reported **zero known vulnerabilities** in
59
+ the production dependency tree at the time of this audit. That result does not
60
+ cover application logic or prove the absence of undisclosed dependency bugs.
61
+
62
+ After the final fixes, **22 full test suites passed** and the installed-package
63
+ smoke test passed. The new 19-scenario adversarial suite and the existing
64
+ 17-group handoff suite are included in that result.
65
+
66
+ The live Cursor app connection was reloaded and tested in the existing
67
+ “Memoir project continuation” conversation. A harmless `memoir_work_check`
68
+ request returned the explicit MCP-execution refusal. A subsequent
69
+ `memoir_work_resume` still returned both saved answers and the unauthenticated
70
+ receipt warning. No fallback command was run for this denial probe. This verifies
71
+ the active client received the hardened server, not only an isolated test copy.
72
+
73
+ ## What this does not secure
74
+
75
+ - **Valid local receipt forgery remains possible.** A process with ledger write
76
+ access can change a failed exit code to zero and construct valid-looking
77
+ metadata. The suite demonstrates this. Receipts are local, unauthenticated
78
+ observations, not signed attestation or release authorization.
79
+ - **Semantic prompt injection is not solved.** Escaping blocks structural
80
+ spoofing and active Markdown, but an AI can still mishandle hostile text.
81
+ Stored claims and source labels never grant authority.
82
+ - **The CLI is not an independent sandbox.** It executes the authorized command
83
+ with the terminal client's permissions and environment. Declared input hashes
84
+ are evidence scope, not restrictions on what that process can read or write.
85
+ - **Same-user hostile filesystem races are outside the boundary.** Stable
86
+ symlinks and traversal are rejected, but this is not OS-level isolation from
87
+ a process that can concurrently alter the project, server installation or
88
+ ancestor directories. A stronger boundary needs OS-enforced isolation and
89
+ separately protected evidence signing.
90
+ - **Privacy detection is heuristic.** Arbitrary personal sentences and every
91
+ encoded credential cannot be identified automatically. Local files/backups
92
+ are plaintext, and connected AI clients receive the project context they use.
93
+ - **Scope is the new handoff.** This is a focused source and local adversarial
94
+ audit, not an independent penetration test of all legacy Memoir commands,
95
+ hosted APIs, cloud authorization or cross-tenant isolation. Those were not
96
+ exercised against a live service here.
97
+
98
+ ## Local audit trail
99
+
100
+ Baseline and rerun logs are beside this checkout:
101
+ `../memoir-adversarial-before.log`,
102
+ `../memoir-adversarial-additional-before.log`,
103
+ `../memoir-adversarial-after.log`, and
104
+ `../memoir-security-full-tests.log`. The dependency result is
105
+ `../memoir-handoff-npm-audit.json`. Current execution receipts and the saved audit
106
+ decision are in the ignored `.memoir/work.json`; none of these logs were published.
@@ -0,0 +1,129 @@
1
+ # Local handoff validation — 2026-09-06
2
+
3
+ The Codex → Cursor → Codex workflow completed in this Memoir checkout on this
4
+ Mac. Both continuations used the saved answers and reused the saved integration
5
+ check. This exercise was performed before publication; the counts below describe that local candidate.
6
+
7
+ This report records the original functional exercise. A subsequent
8
+ [adversarial audit](HANDOFF-SECURITY-AUDIT.md) found and fixed security gaps.
9
+ In the hardened version, check execution is available through the CLI under
10
+ normal terminal permissions; the MCP check tool deliberately refuses commands.
11
+ Memory reads also omit Git dirty-status checks to avoid executing repository
12
+ hooks. Later receipts supersede the original receipts described below.
13
+
14
+ For everyday use, open the **same folder and branch** in either tool and say
15
+ **“Continue this project.”** Run one-time setup in the project you want to continue. See
16
+ [the usage guide](PROJECT-HANDOFF.md) for the full reference.
17
+
18
+ ## What was tested in actual clients
19
+
20
+ | Step | Observed result | Evidence |
21
+ |---|---|---|
22
+ | Codex, first session | Saved the goal, two user answers, an output-privacy decision, a real integration receipt and Cursor's next task | Ledger revisions 1–6; local Codex event log |
23
+ | Cursor desktop, local environment | Resumed without receiving the task description again, wrote the requested guide, marked its task done and left a review for Codex | Cursor conversation “Memoir project continuation”; ledger revisions 7–8; guide file |
24
+ | Codex, fresh return session | Found Cursor's completed task, reviewed and corrected the guide, preserved answers and marked the review done | Ledger revision 13; local Codex return event log/result |
25
+ | Cursor MCP connection | Initially disabled; enabling only this project's Memoir source connected four tools. A follow-up direct `memoir_work_resume` call returned both answers and the matching check | Cursor Customize → MCPs and the conversation's tool result |
26
+
27
+ Codex ran using the app-bundled **CLI 0.153.4**, with the existing configured
28
+ model, in two fresh sessions. Cursor was the installed **desktop app 3.17.19**,
29
+ using **This Mac**, this checkout and `fix/audit-reliability`. This was not a
30
+ separate fresh Codex desktop-chat test. The older standalone Codex CLI 0.146.0
31
+ could not run the configured model; it was left unchanged.
32
+
33
+ Codex loaded the project MCP configuration, but its test sessions' `never`
34
+ approval policy refused MCP calls. Both sessions successfully used the generated
35
+ CLI fallback. No approval policy or model setting was relaxed. Cursor's initial
36
+ work also used the fallback before its new project connection was enabled.
37
+ Successful server setup alone is not treated as proof of client acceptance.
38
+
39
+ ## Did it reduce repeated work?
40
+
41
+ - Both continuations reused the original delivery and privacy answers; their
42
+ record revisions remained 2 and 3. No repeated answered question was observed.
43
+ - The integration check was executed **once during the three-leg round trip**.
44
+ Cursor and returning Codex both reused its revision-5 receipt because its
45
+ declared files and runtime still matched.
46
+ - Cursor obtained its task from the handoff, and Codex obtained the review from
47
+ Cursor's update. Neither continuation prompt copied those task descriptions
48
+ or the earlier conversation.
49
+ - Returning Codex added a separate documentation check. Its first attempt
50
+ mishandled Git's no-index exit status; the corrected check passed. Memoir
51
+ retained the failed receipt and the later pass. This was additional work on
52
+ a new check, not a rerun of the saved integration check.
53
+
54
+ This demonstrates continuity in one useful local exercise. It is not a timed
55
+ comparison against working without Memoir, a guarantee of fewer questions in
56
+ every task, or evidence that agents will always follow the instructions.
57
+
58
+ ## Changed conditions and rechecks
59
+
60
+ After the round trip, the setup message was clarified and the integration
61
+ fixture was strengthened to actually exercise paths containing spaces and
62
+ quotes. A fresh resume correctly changed the integration result to
63
+ `needs-recheck` and named:
64
+
65
+ ```text
66
+ Changed input: src/work/setup.js
67
+ Changed input: test-work-handoff.mjs
68
+ ```
69
+
70
+ The documentation check also became stale because it included the setup source.
71
+ The guide then gained the final usage and removal instructions. Targeted reruns
72
+ passed: integration receipt **14**, documentation receipt **15**. Both now show
73
+ matching declared inputs. The warning cleared because the checks ran against
74
+ the new files; no completion flag was manually substituted for a check.
75
+
76
+ Relevant file changes, missing files, changed local Node runtime, newly added
77
+ dependency manifests, failed executions and changes during a run trigger
78
+ specific recheck reasons. Unrelated documentation edits do not invalidate the
79
+ integration result. External observations always need current verification:
80
+ for example, a prior Stripe dashboard check does not prove today's settings.
81
+ Only the declared inputs are covered, so agents must include all relevant files.
82
+
83
+ ## Implementation and verification
84
+
85
+ - Separate project ledger and MCP server; no global personal-memory or transcript
86
+ import. Records include source, rationale, branch, revisions and next-action
87
+ completion. Corrections reject stale revisions; retractions retain history.
88
+ - Checks execute an argument array and retain exit status, timestamps, input
89
+ fingerprints and an output digest. Raw terminal output is discarded.
90
+ - Setup preserves unrelated project settings and backs up changed existing
91
+ files. Existing conflicting Memoir connections are preserved with a warning.
92
+ No unrelated global configuration was edited. Only the new project source
93
+ was enabled in Cursor's UI.
94
+ - **21 test suites passed**, including the project handoff suite. The final
95
+ focused run passed **17 groups**, including privacy canaries, actual process
96
+ execution, stale-input detection, concurrency, settings preservation, real
97
+ MCP restarts and fallback paths containing spaces and quotes.
98
+ - The **installed-package smoke test passed** with the new project CLI, setup,
99
+ check receipt and MCP resume, alongside the existing backup/restore tests.
100
+ - The guide's examples, command help and whitespace were checked; its semantic
101
+ content was also reviewed against the implementation. A passing syntax check
102
+ alone does not establish that a guide is correct.
103
+
104
+ ## What remains manual or limited
105
+
106
+ - Choose the same local checkout and branch, then ask the next agent to continue.
107
+ The ledger is ignored by Git: GitHub pushes, another worktree or another
108
+ computer do not carry it. The older Memoir backup commands do not sync this
109
+ new ledger.
110
+ - A client can require project trust or MCP approval. Cursor's connection is
111
+ enabled here; Codex can use the fallback under its existing policy.
112
+ - Agents must save important decisions and use Memoir's check command/tool.
113
+ Ordinary shell checks and unsaved conversation are not captured by a hook.
114
+ - Personal-scope records and recognized secrets are rejected, and raw output is
115
+ not retained. Detection is heuristic. Project files and backups are plaintext
116
+ locally; connected AI clients receive the project context used for the task.
117
+ This is not an isolation barrier against a process with filesystem access.
118
+ - External app settings can change independently. Evidence is scoped and
119
+ attributable, but local receipts and source labels are not cryptographic
120
+ authentication against a process allowed to edit the ledger.
121
+
122
+ ## Local evidence locations
123
+
124
+ The ignored `.memoir/` directory contains `work.json`, the refreshed
125
+ `HANDOFF.md`, both Codex event logs and results, `after-input-change.json`, and
126
+ the final integration/documentation receipts. Exact setup backups are under
127
+ `.memoir/setup-backups/`. Full-suite and package-test logs are beside this
128
+ checkout in `../memoir-handoff-full-tests.log` and
129
+ `../memoir-handoff-packed-test.log`. These local logs are not published.
@@ -0,0 +1,17 @@
1
+ # MCP SDK v2 compatibility assessment
2
+
3
+ Checked 5 September 2026. Memoir currently declares `@modelcontextprotocol/sdk ^1.29.0` and Node `>=18`.
4
+
5
+ The [official SDK repository](https://github.com/modelcontextprotocol/typescript-sdk) documents v2 as stable for the 2026-07-28 protocol specification, with separate server/client packages and Standard Schema support. The npm manifests for [server 2.0.0](https://registry.npmjs.org/@modelcontextprotocol/server/2.0.0) and [client 2.0.0](https://registry.npmjs.org/@modelcontextprotocol/client/2.0.0) both declare Node `>=20`. The upstream README promises v1 bug/security fixes for at least six months after v2 release. This is a planned compatibility migration, not evidence that Memoir's current SDK is vulnerable.
6
+
7
+ A direct dependency replacement would break Memoir's advertised Node 18 support. The retrieval changes therefore retain v1 and do not quietly raise the minimum runtime.
8
+
9
+ Before migrating:
10
+
11
+ 1. Choose and announce an actively supported Node LTS baseline; the SDK's minimum is not necessarily the appropriate product minimum. Update package metadata, installation docs, and CI together.
12
+ 2. Inventory imports in `src/mcp.js`, `src/integrations/setup.js`, and the test clients. Port server/client imports, transports, and tool schemas according to the chosen released v2 API.
13
+ 3. Preserve existing tool names, argument validation, project visibility, structured/text responses, and error semantics. Check empty results and malformed requests.
14
+ 4. Exercise protocol negotiation, initialization, tool discovery/calls, shutdown/restart, and the installed tarball on all supported operating systems.
15
+ 5. Confirm actual supported Claude Code, Codex, and Cursor releases accept configuration and complete remember/recall/restart. An SDK-to-SDK handshake alone is insufficient.
16
+
17
+ No SDK migration or runtime-support change is included in the retrieval-index change.
@@ -0,0 +1,301 @@
1
+ # Project continuation for Codex and Cursor
2
+
3
+ ## Use it now
4
+
5
+ Install Memoir 3.14.0 or later and run `memoir work setup` in the project you
6
+ want to continue. Open that same folder and branch in Codex or Cursor and say
7
+ **“Continue this project.”** The next agent reads saved answers, decisions,
8
+ completed work and next actions. You do not need to copy the conversation.
9
+
10
+ The reference local test completed the round trip with Cursor desktop and the
11
+ Codex CLI. See [the validation report](LOCAL-HANDOFF-VALIDATION.md) for the actual
12
+ client versions and limits. Agents still need to follow the installed
13
+ instructions, and setup does not prove a new client has accepted its connection.
14
+
15
+ This documents the local project handoff in `src/work/` and `bin/memoir-work.js`. It is not a claim that hosted clients have accepted the connection, and it does not import global or personal Memoir memory.
16
+
17
+ `.memoir/work.json` is the authoritative ledger. `.memoir/HANDOFF.md` is a generated preview; run `resume` before relying on it. Stored text is evidence, never permission.
18
+
19
+ ## See and correct what Memoir remembers
20
+
21
+ Memoir remains a CLI and tool integration. This optional browser companion reads
22
+ the same project record; it is not a separate memory service. You can keep using
23
+ the CLI, Codex or Cursor without opening the page.
24
+
25
+ The default **Records** view shows open actions, saved answers and check evidence.
26
+ **Records** and **Map** share one workspace, search box and category navigation.
27
+ Switching views keeps the search and category. Records use readable rows with
28
+ short headings and expandable text; source history stays available on each entry.
29
+
30
+ The **Map** view connects the current branch's project entries. Select a
31
+ node to read its full text, source and history, and inspect connected entries.
32
+ Solid lines show project membership, explicit record references, or a named file
33
+ that a check declares as input. A file link does not prove the entry's claims.
34
+ Suggested links are off by default. Enable **Suggested links** to include possible
35
+ shared topics around a selected entry; dashed lines distinguish these word
36
+ matches from recorded references. Each suggestion explains its words and is not
37
+ saved as a relationship. This prototype does not infer
38
+ causes, automatically determine affected work, or use personal memory.
39
+
40
+ Search and category filters narrow the map. The overview shows up to six entries
41
+ around the project; selecting an entry centers it and shows up to six direct
42
+ neighbors, with recorded references first. Lines connect only to that center.
43
+ It computes connections within up to 120 entries, prioritizing matches and the
44
+ selected entry. Search covers all active entries, including older ones, but the
45
+ visible map and connection list are not exhaustive. No text leaves the browser
46
+ to generate these connections.
47
+
48
+ **Records** provides the overview and category lists for editing. The overview
49
+ shows every open action as a short row; **Details** opens its explanation and
50
+ controls. Saved answers and recent decisions start collapsed. Matching checks
51
+ remain available from the summary and Checks category; only checks needing
52
+ review appear in the overview. Long entries in category lists expand with
53
+ **Read full entry**; completed actions remain under **Next actions**. Both views
54
+ use the same correction controls and project record. **Connections** opens a
55
+ record in the map; **Open in Records** returns to that entry's category. Removed
56
+ items use the Records recovery list and do not enter the active map.
57
+
58
+ Selecting a map entry opens its details beside the map in wide windows and below
59
+ it in narrow windows. Keyboard focus follows the selected context. Saving from
60
+ either view selects the saved entry, clears the old search and opens its category
61
+ so a filter cannot hide a successful save. Both views search covered file paths as
62
+ well as record text and sources. Overview search includes all matching records,
63
+ including completed actions and goals, without the overview's two-per-group limit.
64
+ See [the project map trial](PROJECT-MAP-TRIAL.md) for
65
+ tested behavior and the limits of suggested connections.
66
+
67
+ Run `memoir work view` in your project (or `node bin/memoir.js work view`
68
+ from a source checkout), or ask the agent
69
+ “Open my Memoir project view.” The browser shows the current branch's answers,
70
+ decisions, checks, goals and next steps. Setup is not needed again for each use.
71
+ Keep the terminal process running while using the view; Ctrl+C stops it.
72
+ `--no-open` prints the access link without launching a browser, and `--port N`
73
+ chooses a local port. The default chooses an available one.
74
+
75
+ - **Correct** saves a new version that the next agent resume receives. Source and
76
+ earlier versions remain available on the card.
77
+ - **Remove from handoff** hides an item from agents. **Removed → Restore to
78
+ handoff** brings back a record. This is reversible removal, not permanent
79
+ deletion; there is no project-history purge control yet.
80
+ - **Mark done** preserves a completed next step so another session knows it was
81
+ finished. **Reopen** makes it active again.
82
+ - **Needs recheck** names changed inputs or explains a failed/external result.
83
+ The view cannot run commands or edit check receipts. A removed receipt needs
84
+ a new authorized check, not a restore-to-pass button.
85
+ - If another session edits the item, the draft stays open. **Review latest
86
+ version** shows the saved version; compare it, choose **Keep my draft and
87
+ continue**, then save. Another intervening change is rejected again. If the
88
+ branch changed or the item was removed, review that state before proceeding.
89
+
90
+ While a save is pending, the editor keeps its fields and close controls locked.
91
+ A request stops waiting after 15 seconds. An interrupted response does not prove
92
+ that the save failed: the server may already have saved it. The draft stays open;
93
+ use **Review latest version** to find the saved record before retrying. Retrying
94
+ the same open draft cannot create a second record. Closing or reloading the tab
95
+ still discards unsaved drafts; they are not written into browser storage.
96
+
97
+ The view listens only on this computer at 127.0.0.1. Its temporary access link
98
+ opens this process's project data; keep it private and do not add it to a handoff.
99
+ The browser removes the token from the visible URL and keeps it only in that
100
+ browser tab's session storage. Reopen from the terminal's full link after losing
101
+ that session. There is no account, upload, command runner or settings editor.
102
+ The agent's permissions and the local plaintext/unsigned-evidence limits below
103
+ still apply. Other same-user processes are not an isolation boundary.
104
+
105
+ ## One-time setup
106
+
107
+ From the Memoir source checkout after installing its dependencies:
108
+
109
+ ```bash
110
+ node bin/memoir-work.js --project "$(pwd)" setup --tools codex,cursor
111
+ ```
112
+
113
+ To connect another project on this computer, replace `"$(pwd)"` with that
114
+ project's absolute folder path. Keep the Memoir installation in place: the
115
+ generated connection and fallback refer to it. For this tested Cursor version,
116
+ open **Customize → MCPs → memoir-work** and enable the project source if it shows
117
+ Disabled. Existing unrelated connections remain unchanged.
118
+
119
+ `--tools` accepts `codex`, `cursor`, or both (default: both). Setup verifies a live MCP handshake: the server must expose `memoir_work_resume`, `memoir_work_record`, `memoir_work_check`, and `memoir_work_retract`.
120
+
121
+ If the handshake succeeds, setup writes only the files that actually change:
122
+
123
+ | File | Role |
124
+ |---|---|
125
+ | `AGENTS.md` | Managed instruction block (`<!-- memoir:project-work -->` … `<!-- /memoir:project-work -->`), for either tool selection |
126
+ | `.cursor/rules/memoir-work.mdc` | With `cursor`: same instructions; a new file gets `alwaysApply: true`, existing frontmatter is preserved |
127
+ | `.cursor/mcp.json` | With `cursor`: `mcpServers.memoir-work` stdio entry |
128
+ | `.codex/config.toml` | With `codex`: `mcp_servers.memoir-work` stdio entry |
129
+ | `.gitignore` | Keeps `/.memoir/`, `/.codex/config.toml`, `/.cursor/mcp.json`, and `/.cursor/rules/memoir-work.mdc` out of ordinary commits |
130
+
131
+ The MCP entry runs `src/work/server.js` with `MEMOIR_PROJECT_ROOT` set to the project directory and `DO_NOT_TRACK=1`. Previous contents of changed, non-empty text files are copied under `.memoir/setup-backups/<uuid>/` before edits are written. Empty or newly created files have no backup entry. Setup is not a transaction across all files; an interrupted write can leave partial edits.
132
+
133
+ A second setup with unchanged generated content leaves the listed files alone, but still verifies the server and refreshes `.memoir/HANDOFF.md`. The `.gitignore` additions apply for either tool selection.
134
+
135
+ Text outside the managed instruction block and existing TOML comments are preserved. Cursor configuration must be valid JSON: comments are unsupported, and adding a connection rewrites JSON formatting while preserving unrelated settings and servers. An existing `memoir-work` entry is left unchanged; a different command, args, or project root produces a CLI-fallback warning. Other differences, such as `DO_NOT_TRACK`, are not reconciled. Parsing errors, detected malformed instruction markers, or an explicitly invalid MCP server map or Memoir connection (including null, false, zero, empty strings and arrays) abort before the planned edits are written. This is not comprehensive client-configuration validation.
136
+
137
+ After setup, open the project in Cursor or Codex, accept the normal project/MCP trust prompt if shown, and start with “Continue this project.” Setup alone does not verify client acceptance; see the recorded observation below for this project's tested routes.
138
+
139
+ ## Daily Codex / Cursor workflow
140
+
141
+ 1. **Resume first.** Call `memoir_work_resume` (or `node bin/memoir-work.js --project "$(pwd)" resume`). Reuse recorded answers and applicable checks marked **PASSED; declared inputs still match**. Matching file hashes alone do not make a failed or external check current.
142
+ 2. **Do the recorded next action within the user's current scope.** Mark a next action `done` only after completing it. Pass that record's revision as `expected_revision` from the current resume, not the overall handoff revision.
143
+ 3. **Record as you go.** Save explicit project decisions, resolved questions, and the next action with `memoir_work_record`. Identify the source. Do not save personal preferences, credentials, raw transcripts, or guesses as answers.
144
+ 4. **Capture checks through Memoir's CLI.** Run `memoir work check` through the client's normal terminal permissions and sandbox. The MCP check tool deliberately refuses execution. An ordinary shell pass outside the wrapper is not recorded evidence.
145
+ 5. **Update the action at the stopping point.** Save its completion or remaining authorized work and relevant decisions. If the action is complete, no additional task needs to be invented. Updates are written immediately; no separate handoff request is needed.
146
+
147
+ MCP tools (stdio server, project-bound):
148
+
149
+ | Tool | Purpose |
150
+ |---|---|
151
+ | `memoir_work_resume` | Current branch: answers, decisions, next actions, and checks with freshness |
152
+ | `memoir_work_record` | Save a project-only `goal`, `answer`, `decision`, or `next` |
153
+ | `memoir_work_check` | Refuse host command execution and direct existing clients to the CLI check command |
154
+ | `memoir_work_retract` | Hide a mistaken record from the current view; history stays local |
155
+
156
+ CLI fallback (`memoir work` delegates to the same entry):
157
+
158
+ Use the direct `bin/memoir-work.js` entry for the project-only workflow. Generated project instructions contain absolute, quoted paths to Node, this entry, and the project root; use those if `node` is unavailable on the client PATH. A configured MCP tool can also be unavailable because its call requires approval under a policy that forbids approval. Use the authorized CLI fallback in that case; do not change approval policies or app settings as part of continuation.
159
+
160
+ ```bash
161
+ node bin/memoir-work.js --project "$(pwd)" resume
162
+ node bin/memoir-work.js --project "$(pwd)" resume --json
163
+ node bin/memoir-work.js --project "$(pwd)" record --file .memoir/record-input.json
164
+ node bin/memoir-work.js --project "$(pwd)" check CHECK_ID --title 'What this proves' --files SOURCE_FILE TEST_FILE -- node TEST_FILE
165
+ node bin/memoir-work.js --project "$(pwd)" retract RECORD_ID --revision N --category record
166
+ ```
167
+
168
+ `--file -` reads record JSON from stdin. For `record`, provide exactly one of `--json` or `--file`; a record file must be project-relative and at most 16 KiB. Record fields: `id`, `kind` (`goal` \| `answer` \| `decision` \| `next`), `text`, `source`; optional `answer`, `why`, `status`, `expected_revision`, `scope`. `scope` defaults to `project` and accepts no other value.
169
+
170
+ ## Correction
171
+
172
+ Resume first. Corrections require the target record's current revision as `expected_revision`. History is appended; the latest matching branch record is what resume shows unless retracted. The numbers and IDs below are illustrative: use an existing record's actual ID and revision, and only describe a user correction when one was actually given.
173
+
174
+ Create `.memoir/record-input.json` (gitignored under `/.memoir/`):
175
+
176
+ ```json
177
+ {
178
+ "id": "answer.provider",
179
+ "kind": "answer",
180
+ "text": "Payment provider?",
181
+ "answer": "CorrectedPay",
182
+ "source": "User correction after resume",
183
+ "expected_revision": 3
184
+ }
185
+ ```
186
+
187
+ ```bash
188
+ node bin/memoir-work.js --project "$(pwd)" record --file .memoir/record-input.json
189
+ ```
190
+
191
+ Rules from the current implementation:
192
+
193
+ - Omitting `expected_revision` on an existing ID fails.
194
+ - A new ID may omit `expected_revision` or pass `0`. A non-zero revision on a missing ID fails.
195
+ - A correction cannot change `kind`; use another ID.
196
+ - Only `next` records may use `status: "done"`. An `answer` requires `answer`.
197
+ - IDs match `^[a-zA-Z0-9][a-zA-Z0-9._-]{0,79}$`. Text fields are 1–2000 characters after trim.
198
+
199
+ MCP equivalent: `memoir_work_record` with the same object under `record`.
200
+
201
+ ## Retraction
202
+
203
+ Retraction removes the record from the current resume view. The ledger keeps the history, and the same ID can be recorded again.
204
+
205
+ ```bash
206
+ node bin/memoir-work.js --project "$(pwd)" resume
207
+ node bin/memoir-work.js --project "$(pwd)" retract next.test --revision 12 --category record
208
+ ```
209
+
210
+ Then record a replacement, passing that same record revision as `expected_revision` (12 in this example), not the newer revision of the retraction or overall handoff. Resume again before the correction; the retracted record is hidden, so retain its original revision or consult its latest entry in `.memoir/work.json`.
211
+
212
+ ```json
213
+ {
214
+ "id": "next.test",
215
+ "kind": "next",
216
+ "text": "Add test",
217
+ "source": "Correction after retract",
218
+ "status": "open",
219
+ "expected_revision": 12
220
+ }
221
+ ```
222
+
223
+ `--category check` retracts a saved check the same way. Resume before retracting; a stale revision is rejected. MCP: `memoir_work_retract` with `id`, `expected_revision`, and optional `category` (`record` default).
224
+
225
+ ## Check evidence and freshness
226
+
227
+ `memoir work check` spawns argv with `shell: false` in the project directory. The MCP server never runs that command: memory-tool approval must not grant a separate host shell. Use the CLI through the client's normal terminal permissions. The CLI stores:
228
+
229
+ - actual `exit_code` (and `signal` / start error if any)
230
+ - SHA-256 of each declared input, plus any present common manifests (`package.json`, `package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `requirements.txt`, `pyproject.toml`, `uv.lock`)
231
+ - `inputs_stable` (hashes unchanged during the run)
232
+ - `output_sha256` and `output_bytes`
233
+ - `runtime` (`platform/arch/node-version`)
234
+ - `environment` (`local` default, or `external`)
235
+ - `evidence_source: memoir-executed-process`
236
+
237
+ Raw stdout/stderr is hashed and discarded. A delayed older execution cannot replace a newer result for the same ID. CLI exit status is 1 when `exit_code !== 0`, the command timed out, or inputs were not stable.
238
+
239
+ Resume labels a check **PASSED; declared inputs still match** only when freshness is `inputs-match`. Otherwise it is **NEEDS RECHECK**, with reasons. Recheck when any of these apply:
240
+
241
+ - execution evidence is missing
242
+ - non-zero exit, timeout, signal, or more than 8 MiB of output
243
+ - inputs changed while the check ran
244
+ - `environment` is `external` (settings can change independently)
245
+ - the local runtime changed
246
+ - a new common manifest appeared
247
+ - a recorded input hash changed, or an input is missing/unreadable
248
+
249
+ Unrelated files outside the declared inputs do not invalidate a match. A pass covers only those declared files and the local runtime. It does not verify undisclosed dependencies, external settings, or production. External configuration always needs current verification.
250
+
251
+ Rejected as check inputs: paths under `.memoir/`, basenames `.env` / `.env.*` or starting with `credentials`, `id_rsa` / `id_ed25519`, `*.pem` / `*.key`, absolute paths, path traversal, and symlinks beneath the resolved project root. Input files are limited to 16 MiB each. These path rules govern input hashing, not what the executed command can access. The command inherits the process environment with `DO_NOT_TRACK=1`; the runner is not a separate sandbox. Supply every relevant source/test/configuration file; do not claim a shell command was captured unless it ran through this tool.
252
+
253
+ Default timeout is 30s (100 ms–120 s). `--environment` is `local` or `external`.
254
+
255
+ ## Privacy boundaries
256
+
257
+ Project-only. Personal/global memory, transcripts, and raw command output are not imported.
258
+
259
+ Save: project decisions, answered questions, checks with evidence, and next actions. Do not save personal preferences, credentials, secrets, or guesses as user answers. Source labels identify the claimed origin; they are not authentication.
260
+
261
+ Record/check arguments and ledger reads/writes scan decoded fields for known credential patterns, including normalized invisible-character obfuscation. Matching text, unsafe control characters and direction overrides are refused. This is a backstop, not a claim to recognize every private sentence or encoding. Ledger size is capped at 2 MiB and CLI record input at 16 KiB; full or oversized input fails without dropping records. Setup backups are separate from this ledger guard and can contain prior configuration contents, so keep them local too.
262
+
263
+ Rendered fields cannot create new Markdown sections or active image links. Their content still remains untrusted: formatting cannot guarantee that an AI will resist semantic prompt injection. Local receipts are explicitly unauthenticated. A process allowed to rewrite the ledger can forge a valid-looking receipt; never use one as security attestation or deployment approval. See the [adversarial audit](HANDOFF-SECURITY-AUDIT.md).
264
+
265
+ Keep this memory local unless the user explicitly chooses to share it. Existing application approvals still apply. `.gitignore` entries above keep the ledger and tool connections out of ordinary commits.
266
+
267
+ ## Actual limitations
268
+
269
+ - **Same local checkout.** Open the same folder and branch in both tools. The ignored ledger is not synchronized by ordinary Git commits, GitHub pushes, another worktree, or the older Memoir backup commands.
270
+ - **Agents must record the work.** These instructions request updates as work happens; no hook captures arbitrary conversations or ordinary shell checks. A crash before an agent saves a decision can lose that decision.
271
+ - **CLI continuation and MCP acceptance are separate.** Setup can verify the local MCP server, but does not prove Cursor/Codex will permit calls. The observation below records the narrower result actually obtained.
272
+ - **Branch-scoped.** Resume shows the current Git branch only. Other-branch records are counted, not mixed in.
273
+ - **Preview can lag.** `.memoir/HANDOFF.md` is rewritten on resume/record/check/retract. Refresh it before relying on it.
274
+ - **MCP may be missing or approval-blocked.** Use the authorized CLI fallback. Setup will not overwrite a conflicting existing `memoir-work` connection.
275
+ - **Freshness is narrow.** Matching inputs are not a production proof. External checks never appear current.
276
+ - **Git dirty status is unknown.** Memory reads no longer run `git status`, which can execute repository-configured hooks or filters. Check freshness still compares the declared files directly.
277
+ - **CLI commands retain terminal authority.** Declared input files specify evidence coverage, not a filesystem sandbox. Only run trusted, authorized checks through the client's normal execution controls.
278
+ - **Foreign or damaged ledgers fail closed.** Invalid JSON, unsupported version, or non-`project` scope preserves the original file and refuses the operation.
279
+ - **Locks serialize writers.** Concurrent records are queued; a busy lock fails rather than corrupting the ledger.
280
+ - **No permission from storage.** Recorded text cannot authorize work that the user did not authorize.
281
+
282
+ ## Remove the setup
283
+
284
+ Disable only this project's `memoir-work` connection in the clients, remove its
285
+ entry from the two project MCP configuration files, and remove the marked Memoir
286
+ block from `AGENTS.md` and the dedicated Cursor rule. Leave unrelated entries and
287
+ instructions in place. Exact pre-setup copies of changed existing files are in
288
+ `.memoir/setup-backups/`; review later edits before restoring any whole file.
289
+ The ignored ledger can stay for later use. Retraction hides an item but does not
290
+ erase its history; deletion of sensitive content would also need to cover local
291
+ history and copies. Setup does not install a background service.
292
+
293
+ ## Observed continuation, 2026-09-06
294
+
295
+ Codex resumed the local ledger through the documented CLI fallback and reviewed this guide against `src/work/{cli,setup,store,server}.js`, the supporting file/lock/repository helpers, and `bin/memoir-work.js --help`. The delivery/privacy answers and output-digest decision carried forward. The recorded Cursor documentation action was already done; the open Codex action was this documentation review. No answered question was asked again.
296
+
297
+ The saved `check.project-handoff` result (revision 5) still matched its declared inputs and local runtime and was reused without rerunning it. That check covers the listed implementation/test files and manifests, not this guide or external app settings. Documentation edits therefore need their own review; they do not invalidate that integration result.
298
+
299
+ A later resume carried forward `decision.client-route` (revision 10), whose source reports that Cursor's project connection was enabled, showed four tools, and successfully called `memoir_work_resume` on 2026-09-06. This is saved project evidence from the local client test; the documentation review did not repeat that test or inspect external app settings.
300
+
301
+ In this Codex session, the configured MCP resume call returned “MCP tool call requires approval, but approval policy is never.” The documented CLI fallback succeeded. No policy or app setting was changed by this review. Successful CLI continuation does not establish successful Codex MCP use. Source labels are claims, not authentication, and saved client observations do not verify current external settings. Those settings and current client acceptance need verification before claiming they still work; such verification was outside this documentation-only continuation.