pi-jarvis 1.9.1 → 1.10.2

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 (58) hide show
  1. package/AGENTS.md +23 -3
  2. package/README.md +159 -27
  3. package/dist/archive-crypto.d.ts +55 -0
  4. package/dist/archive-crypto.d.ts.map +1 -0
  5. package/dist/archive-crypto.js +274 -0
  6. package/dist/archive-crypto.js.map +1 -0
  7. package/dist/archive-extension.d.ts.map +1 -1
  8. package/dist/archive-extension.js +13 -2
  9. package/dist/archive-extension.js.map +1 -1
  10. package/dist/archive-import.d.ts +4 -1
  11. package/dist/archive-import.d.ts.map +1 -1
  12. package/dist/archive-import.js +25 -11
  13. package/dist/archive-import.js.map +1 -1
  14. package/dist/archive-keychain.d.ts +37 -0
  15. package/dist/archive-keychain.d.ts.map +1 -0
  16. package/dist/archive-keychain.js +100 -0
  17. package/dist/archive-keychain.js.map +1 -0
  18. package/dist/archive-migration.d.ts +13 -0
  19. package/dist/archive-migration.d.ts.map +1 -0
  20. package/dist/archive-migration.js +302 -0
  21. package/dist/archive-migration.js.map +1 -0
  22. package/dist/archive-secret-input.d.ts +106 -0
  23. package/dist/archive-secret-input.d.ts.map +1 -0
  24. package/dist/archive-secret-input.js +600 -0
  25. package/dist/archive-secret-input.js.map +1 -0
  26. package/dist/archive-service.d.ts +16 -3
  27. package/dist/archive-service.d.ts.map +1 -1
  28. package/dist/archive-service.js +114 -24
  29. package/dist/archive-service.js.map +1 -1
  30. package/dist/archive-sqlite.d.ts +35 -0
  31. package/dist/archive-sqlite.d.ts.map +1 -0
  32. package/dist/archive-sqlite.js +167 -0
  33. package/dist/archive-sqlite.js.map +1 -0
  34. package/dist/archive-store.d.ts +36 -1
  35. package/dist/archive-store.d.ts.map +1 -1
  36. package/dist/archive-store.js +243 -24
  37. package/dist/archive-store.js.map +1 -1
  38. package/dist/archive-unlock.d.ts +68 -0
  39. package/dist/archive-unlock.d.ts.map +1 -0
  40. package/dist/archive-unlock.js +268 -0
  41. package/dist/archive-unlock.js.map +1 -0
  42. package/dist/archive-vault-files.d.ts +96 -0
  43. package/dist/archive-vault-files.d.ts.map +1 -0
  44. package/dist/archive-vault-files.js +853 -0
  45. package/dist/archive-vault-files.js.map +1 -0
  46. package/dist/archive-vault.d.ts +37 -0
  47. package/dist/archive-vault.d.ts.map +1 -0
  48. package/dist/archive-vault.js +1296 -0
  49. package/dist/archive-vault.js.map +1 -0
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +92 -16
  52. package/dist/index.js.map +1 -1
  53. package/dist/memory-extension.d.ts +2 -2
  54. package/dist/memory-extension.d.ts.map +1 -1
  55. package/dist/memory-extension.js +1 -1
  56. package/dist/memory-extension.js.map +1 -1
  57. package/docs/archive-encryption-design.md +124 -0
  58. package/package.json +15 -4
package/AGENTS.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Project Scope
4
4
  - `pi-jarvis` is a Pi extension that opens a `/jarvis` side-conversation overlay.
5
- - Core runtime files: `index.ts`, `side-session.ts`, `native-mcp.ts`, `overlay.ts`, `overlay-layout.ts`, `draft-editor.ts`, `transcript-viewport.ts`, `jarvis-branding.ts`, `model-picker.ts`, `jarvis-config.ts`, `session-ref.ts`, `memory-{types,config,content,store,service,extension}.ts`, and `archive-{types,config,store,service,extension,import}.ts`.
5
+ - Core runtime files: `index.ts`, `side-session.ts`, `native-mcp.ts`, `overlay.ts`, `overlay-layout.ts`, `draft-editor.ts`, `transcript-viewport.ts`, `jarvis-branding.ts`, `model-picker.ts`, `jarvis-config.ts`, `session-ref.ts`, `memory-{types,config,content,store,service,extension}.ts`, and `archive-{types,config,store,service,extension,import,crypto,sqlite,keychain,unlock,secret-input,vault-files,vault,migration}.ts`.
6
6
  - Current baseline: Pi 1.0.0 (`@earendil-works` packages), Node.js >=22.19.0. Older Pi hosts are not supported.
7
7
 
8
8
  ## Current `/jarvis-model` and `/jarvis-thinking` Behavior
@@ -65,8 +65,8 @@
65
65
  - Separate settings: `<agentDir>/extensions/pi-jarvis-archive.json` and `.pi/jarvis-archive.json`, top-level `archive`. Controls default global. Settings writers may retry only a raced inode/unlink preflight read once under the existing cooperative lock; policy readers and locked-read races remain fail-closed, with no uncertain write replay. on/model-access on/clear require `--confirm-sensitive`; clear removes settings, not data, and fallback can re-enable. Archive tools are read-only and need modelAccess; humans can inspect with only capture/modelAccess off, but not full off.
66
66
  - `/jarvis-archive` and overlay `/archive` commands are local, immediate, no provider/boot/queue work. Search/read/session default current-project; all-project access is explicit. Model tools cannot change controls, import, or delete. No auto context injection.
67
67
  - Archive accepted finalized journal entries unredacted, including exposed thinking/tool/system/custom/error/inline-image data. Never capture intermediate message_end/tool_result/raw-provider payloads before later redactors. Baseline existing entry IDs on activation, never auto-backfill; parent/header provenance retained. Snapshots are not crash-safe audit logging and cannot recover unpersisted events, earlier truncation or external referenced files. Warn on storage/observation failures, not silent replay.
68
- - Lazy private SQLite FTS5 at `<agentDir>/extensions/pi-jarvis-archive/archive.sqlite`, no automatic retention eviction. 64 MiB raw-entry/index budgets and 64K UTF-16 normalization-context hard rejection, no truncation of accepted raw JSON or silent partial indexing. Identical serialized payloads deduplicate across lanes; conflicting payloads for one identity fail without replacement. Search/read output max 24,000 JSON bytes plus notice; raw read offsets count Unicode codepoints and preserve pagination through output shrinking. Oversized display provenance is explicitly abbreviated; read(part=metadata) / read --metadata pages exact original metadata so every accepted entry stays accessible. Images/signatures are raw-retained, not text-indexed. Never load full payloads for search or scan all raw bodies on open. Inspection uses read-only schema snapshots and bounded observation of a version-zero, truly empty database while a concurrent creator initializes it; release each empty snapshot before waiting. Never let readers initialize/reset storage or retry record writes; unknown nonempty schemas reject.
69
- - Explicit human single-file import streams one selected regular v3 JSONL file, honors its header's project/session provenance, checks live capture/epoch/cancellation at chunk/record boundaries, reports partial commits, never mutates source. No automatic directory scans or legacy auto-migration. Scoped forget-session/prune require --confirm; tombstones stop identical entry resurrection, not all copies. No encryption, sandbox, forensic erase, or hard total-disk-quota claims.
68
+ - Lazy private SQLite FTS5, plaintext by default at `<agentDir>/extensions/pi-jarvis-archive/archive.sqlite`; optional encryption selects a managed generation at `vaults/<UUID>/archive.sqlite` under that fixed root. No automatic retention eviction. 64 MiB raw-entry/index budgets and 64K UTF-16 normalization-context hard rejection, no truncation of accepted raw JSON or silent partial indexing. Identical serialized payloads deduplicate across lanes; conflicting payloads for one identity fail without replacement. Search/read output max 24,000 JSON bytes plus notice; raw read offsets count Unicode codepoints and preserve pagination through output shrinking. Oversized display provenance is explicitly abbreviated; read(part=metadata) / read --metadata pages exact original metadata so every accepted entry stays accessible. Images/signatures are raw-retained, not text-indexed. Never load full payloads for search or scan all raw bodies on open. Inspection uses read-only schema snapshots and bounded observation of a version-zero, truly empty database while a concurrent creator initializes it; release each empty snapshot before waiting. Never let readers initialize/reset storage or retry record writes; unknown nonempty schemas reject.
69
+ - Explicit human single-file import streams one selected regular v3 JSONL file, honors its header's project/session provenance, checks live capture/epoch/cancellation at chunk/record boundaries, reports partial commits, never mutates source. No automatic directory scans or legacy auto-migration. Scoped forget-session/prune require --confirm; tombstones stop identical entry resurrection, not all copies. Plaintext remains the default; optional archive-only encryption protects the active database/index/journals, not original transcripts/shared memory/retained plaintext backups. No sandbox, forensic erase, or hard total-disk-quota claims.
70
70
  - Keep live trust/settings and per-binding stale-definition guards independent of Repo tools. Reader permission changes must not discard pending recording. Main owner closes storage after final archive snapshot; the side owner snapshots finalized entries before revoking its lifetime/context, without closing the shared service. Preserve archive finalization before main boot-generation invalidation. Settings observations propagate between mounted lanes, not by a cross-process watcher.
71
71
 
72
72
  ## Bulk archive import (1.9.0)
@@ -76,6 +76,26 @@
76
76
  - Preserve single-file import compatibility, v3/header provenance, dedup/conflict/tombstone semantics and partial counts. Per-file source failures continue; cancellation/permission/storage-wide failure stops the batch. Sources are never intentionally written. Tests use temporary synthetic session directories only.
77
77
  - `import-report <id> [offset]` pages the latest ephemeral per-file report under the same project/session owner, with enabled archive but no model-access/capture requirement. Bound JSON output to 24,000 bytes, explicitly abbreviate oversized paths and preserve pagination progress. `import-cancel` cancels local imports/previews without changing settings and works while off. No persisted report or automatic context injection.
78
78
 
79
+ ## Optional archive encryption (1.10.0)
80
+ - Password-based archive encryption ships OPTIONAL/OFF by default, agent-wide and independent of archive enablement/capture/modelAccess, shared memory, Repo tools and bridge permissions. No automatic migration, history import, backfill or user-setting changes. Public/private-key support is deferred. `docs/archive-encryption-design.md` documents the shipped operating/security contract, not independent cryptographic certification.
81
+ - Safe setup is human-directed: review configured/effective status, trust and global/project overrides; if avoiding new plaintext archive captures, pause CAPTURE at the effective scope BEFORE enabling/migrating. Global capture off does not override project capture on; explicit global enabled=false blocks project on. Stop all other Pi instances, enable only the intended scope in a trusted project with capture still off, migrate/unlock, verify active storage and chosen plaintext cleanup, unlock again after cleanup, then resume capture explicitly. Never recommend or perform automatic user-control/renderer changes. This does not pause original Pi transcripts or shared memory.
82
+ - Human-only agent-wide syntax (no scope/password/key/path arguments): `/jarvis-archive encryption [status]`; `encryption on|off|cleanup --confirm-sensitive --confirm-stopped`; `encryption recover --rollback --confirm-sensitive --confirm-stopped`; `encryption break-lock --confirm-sensitive --confirm-stopped`; `unlock [session|process|remember|for MINUTES|idle MINUTES]`; `lock`; `password`; `startup manual|prompt|remember`. Overlay `/archive` interception is local, without provider/boot/queue work; password entry closes Jarvis and revokes its transient permissions. Enabled/trusted archive policy is required for unlock/migration/cleanup/data operations; capture/modelAccess may remain off. Status and explicit lock are available while access is paused.
83
+ - `encryption on` migrates to encrypted storage; `encryption off` converts to plaintext without disabling recording. Ordinary `/jarvis-archive off` pauses archive reads/capture and revokes local access without decrypting/deleting files. Password change requires unlock, asks twice, rewraps the SAME data key and ends the local grant: it is not key rotation; old key/envelope backups may still unlock that key's data.
84
+ - Use a random 256-bit data key with authenticated password wrapping (fixed asynchronous scrypt and AES-256-GCM); encrypt the SQLite database and its FTS/journal/WAL content, not just message bodies. Ordinary encrypted operation has no temporary plaintext database; temp_store must be MEMORY. Passwords are valid Unicode, 1–4096 UTF-8 bytes, without controls/line breaks, with no trimming/normalization. Never fall back to plaintext, ordinary password input, unprotected key files or another credential backend after encryption/remembered-unlock failure.
85
+ - Native dependencies are exact-pinned optional packages, lazy loaded: `better-sqlite3-multiple-ciphers@13.0.3` and `@napi-rs/keyring@2.1.0`. Plaintext stays on node:sqlite. Linux glibc prebuilds require >=2.35; upstream advertises musl/macOS/Windows binaries, but local runtime validation is Linux-only. Remember uses the OS store (Linux explicitly Secret Service, no kernel-keyring downgrade); service/platform authorization applies. Missing/omitted/incompatible dependencies fail closed. Do not execute install scripts or auto-build/download fallback binaries at runtime. Tests use disposable native databases and fake keychains only, never real OS credentials/user archives; preserve host optional peers.
86
+ - Password entry supports ONLY public Pi regular TUI (`pi --tui-mode regular`); fullscreen/unknown/missing/non-TUI refuse. Never change user settings. EVERY submit/cancel, including typed-only Enter/Escape/Ctrl+C, requires a fresh displayed 12-symbol/60-bit code typed + Enter; paste cannot authorize completion. Passwords never enter arguments, environment variables, ordinary editors/history, tools, session entries, notifications or logs.
87
+ - Reserve private-input ownership synchronously before closing Jarvis/yielding. Jarvis/model-picker/main-memory-review admission must use the same gate through preparation, deferred mount, custom lifecycle and cancellation sink. Abort revokes backend work immediately but retains a cancel-only sink until fresh verified exit; never release merely because the backend promise resolves. Cancellable main switch/fork/tree navigation retains the sink and is refused until verified exit. Forced reload/quit/trusted external focus replacement cannot preserve quarantine: abandon without stale done or waiting; disclose this unsupported boundary. Bytes after verified release/host teardown and trusted screen/input/process code are outside protection; hostile input can deny service.
88
+ - Session leases belong to MAIN and are shared with Jarvis; side /new and overlay close preserve them. Default unlock is session. Process/timed/persistent-local grants hand off only across supported main new/resume/fork, preserving fixed/idle deadlines; reload/quit/restart end local grants. Minutes are integers 1–10080. Timed grants check monotonic/wall clocks and access-boundary expiry; idle refreshes only on successful archive data operations, never status/policy checks. No immediate erasure during OS sleep.
89
+ - `unlock remember` authorizes a unique OS account containing the random key, not password, and selects startup remember; `startup remember` requires a live encrypted unlock. Default startup manual and startup prompt clear remembered authorization and lock locally; prompt requests session unlock only on permitted MAIN startup. Explicit nonremember unlock clears prior remembered authorization (remember startup becomes manual). Explicit lock revokes locally first, then durably clears/rotates remembered authorization before best-effort native deletion; report potentially remaining credentials or failed durable revocation honestly. Full-off/untrusted/config errors/restart-required state suppress startup prompts/credentials/authentication; trust restoration does not silently revive revoked grants. Jarvis boot never restores credentials.
90
+ - Locked, transitional, invalid or restart-required vaults block record reads/capture/import/ordinary deletion. Rebaseline capture, cancel imports/previews and reject stale tools; never queue plaintext/backfill after unlock. Observe trust denials through shared policy to revoke keys/pending grants, not just hide tools. Observed durable revisions revoke at operation boundaries, not instant cross-process key erasure/push notification. Final side/main snapshots and side disposal precede boot-generation invalidation, so retiring-side cleanup cannot falsely revoke the main grant.
91
+ - Fixed root `<agentDir>/extensions/pi-jarvis-archive`, strict bounded Ready/Transition metadata `archive.vault.json` (64 KiB), cooperative `archive.vault.lock`, UUID generations `vaults/<UUID>/archive.sqlite`, max EIGHT distinct retired generations. Metadata/wrapping parameters/filesystem identities are not concealed. Canonicalize the selected root only; appended paths remain strict no-follow. Serialize managed operations; stop all other Pi instances, including older versions, before migration/recovery/cleanup. Never auto-steal locks, repair metadata, replay uncertain writes or treat confirm-stopped as stopping processes. Break-lock requires a demonstrably dead local PID on the same host plus identity/token rechecks.
92
+ - Source/active-file observation is stat-only: NEVER open/close another SQLite database/SHM descriptor to inspect a live file, since POSIX close can release the process's native transaction locks. Keep private owner/type/mode/nlink/ancestry and operation-local identity/presence checks. This is not an immutable filesystem snapshot.
93
+ - Throwing trust observations are denial and revoke keys/pending work, including direct policy/status paths. Mid-operation denial revokes immediately; restoring permission cannot reuse that grant. Recheck permits after lease.touch(), which may itself expire/revoke. Import counts retain acknowledged append outcomes despite later guard/release failure; never infer an uncertain COMMIT or retry a write.
94
+ - Stream/verify exact raw JSON spelling/index/provenance/rowids/tombstones to a DISTINCT target, checkpoint/close/fsync before publication, and retain sources until explicit cleanup (including plaintext). Check disk space for both copies; no hard disk-quota guarantee. Record initial legacy-source presence; missing/empty/unsafe/changed known sources require manual inspection/restoration and preservation of unpublished target/Transition, never empty publication or deletion of the only potential copy. An originally absent legacy source is distinct from loss; unknown prototype presence is handled conservatively.
95
+ - Cleanup deletes only recognized retired SQLite files, not active storage or outside backups. Preflight all candidates, auxiliaries before main, live authorization/source checks between deletions; failed cleanup can leave a PARTIAL retained backup, with metadata retained and no automatic uncertain-deletion replay. Encrypted cleanup requires a live lease and existing-active-DB authentication; never recreate a missing active database. Cleanup ends the local grant. Explicit recover --rollback is separate, source-checked, target-only recovery, not migration resume. Timed/idle grants cannot convert to plaintext; explicitly select session/process BEFORE key copying or Transition publication.
96
+ - Preserve native close uncertainty even before a factory returns its handle. Restart-required canonical-root poison survives new facades, aliases, main changes and logical reload/quit, with no unsafe eviction; ONLY ACTUAL PROCESS RESTART resets it. No startup credential/auth work or rollback/cleanup under poison. Grant only after successful lock release and fresh ownership checks. Uncertain publication may already have succeeded; require status/manual inspection/restart, never claim guaranteed Transition or retry automatically. Restart does not repair durable metadata, missing sources or pending transitions.
97
+ - Best-effort buffer wiping/file deletion is NOT forensic erasure. Encryption protects only active archive database/index/journals: original Pi transcripts, shared memory, attachments/exports, retained plaintext sources/backups, previously retrieved/provider context, swap/core dumps and same-user code remain outside the boundary. No sandbox, independently audited cryptography, official/vendor-audited SQLCipher, FIPS or independent certification claims.
98
+
79
99
  ## Git and Release Policy
80
100
  - Every new commit MUST have an annotated **stable version tag `vX.Y.Z`**. No `dev`, alpha, beta, release-candidate, build-metadata, or SHA-only tags. This is a released extension, not a prerelease channel.
81
101
  - Before committing, choose the next unused stable version and update package metadata, lockfile, README, and a dated changelog entry together. Tag every commit, including intermediate and merge commits; never leave a new commit untagged. Run `npm run check:tags`, then push the commit and version tag atomically. Do not move or replace existing tags or rewrite shared history.
package/README.md CHANGED
@@ -4,13 +4,17 @@
4
4
 
5
5
  <img src="https://raw.githubusercontent.com/crustyhacker/pi-jarvis/main/docs/assets/jarvis-logo.svg" alt="JARVIS — Pi / A second lane of thought. Cyan, violet, and pink ASCII chrome." width="720">
6
6
 
7
- ## A cinematic side-conversation overlay for Pi
7
+ ## Give Pi a memory. Give yourself a second lane.
8
8
 
9
- **A second lane of thought—with shared memory and an optional searchable history archive.**
9
+ **Remember decisions. Reuse preferences. Find the conversation that started it all.**
10
10
 
11
- `pi-jarvis` adds `/jarvis`: a polished overlay where you can ask for status, inspect the repo when you explicitly allow it, and send a quiet note or a confirmed redirect back to the main lane.
11
+ Main Pi and Jarvis share **persistent, searchable memory across sessions**—so useful preferences, corrections and project decisions can inform the next conversation. It works in main Pi **even if you never open `/jarvis`**, independently of Repo tools and bridge permissions.
12
12
 
13
- **Remember what matters. Find the original history when you need it.** Main Pi and Jarvis share [persistent memory](#shared-memory); the separate, opt-in [full-session archive](#full-session-archive) adds indexed history search across sessions and, when explicitly requested, projects. **New in the 1.9 series: bulk-import existing Pi sessions with a preview and explicit confirmation.**
13
+ Want the original history, not just useful facts? The separate, opt-in **session archive** adds indexed search, session browsing and preview-confirmed import of existing Pi chats. Optional **password encryption** protects its active database, index and SQLite journals.
14
+
15
+ And `/jarvis` still gives you a polished side-conversation overlay: a second opinion, live main-session context, opt-in repo inspection, and quiet notes or confirmed redirects.
16
+
17
+ **Local storage. User-controlled access. No background model calls or embeddings.** Shared memory is **on in trusted projects** and stored in **plaintext**; recalled facts can be sent to your active model. The separate archive and its encryption are **off by default**. [Understand the controls and privacy boundary](#two-complementary-memory-features).
14
18
 
15
19
  [![CI](https://img.shields.io/github/actions/workflow/status/crustyhacker/pi-jarvis/ci.yml?branch=main&style=for-the-badge&label=CI)](https://github.com/crustyhacker/pi-jarvis/actions/workflows/ci.yml)
16
20
  [![npm version](https://img.shields.io/npm/v/pi-jarvis?style=for-the-badge&color=7c3aed)](https://www.npmjs.com/package/pi-jarvis)
@@ -18,11 +22,18 @@
18
22
  [![Pi extension](https://img.shields.io/badge/Pi-extension-06b6d4?style=for-the-badge)](https://github.com/crustyhacker/pi-jarvis)
19
23
  [![TypeScript](https://img.shields.io/badge/TypeScript-powered-2563eb?style=for-the-badge)](./package.json)
20
24
 
21
- <p><strong>Current version:</strong> 1.9.1</p>
25
+ <p><strong>Current version:</strong> 1.10.2</p>
26
+
27
+ ```bash
28
+ pi install npm:pi-jarvis
29
+ ```
30
+
31
+ [Memory in 60 seconds](#memory-in-60-seconds) · [Search your history](#full-session-archive) · [Import existing sessions](#import-all-existing-pi-sessions) · [Archive encryption](#optional-archive-encryption) · [Open the overlay](#quick-start)
22
32
 
23
33
  <p>
24
34
  <strong>Shared persistent memory</strong> ·
25
35
  <strong>Optional indexed session archive</strong> ·
36
+ <strong>Optional password encryption</strong> ·
26
37
  <strong>Confirmed bulk history import</strong> ·
27
38
  <strong>Persistent side session</strong> ·
28
39
  <strong>Live main-session awareness</strong> ·
@@ -53,27 +64,50 @@
53
64
 
54
65
  ---
55
66
 
56
- ## The pitch
67
+ ## Stop re-explaining your project
57
68
 
58
- The main Pi session should stay on the critical path.
69
+ A fresh session should not mean throwing away every useful decision. `pi-jarvis` gives main Pi and Jarvis a shared place to keep the facts you want to reuse—and an optional archive when you need the original evidence.
59
70
 
60
- `/jarvis` gives you a **second cockpit** for the work that should not interrupt that primary flow:
71
+ | Your workflow | What Jarvis adds |
72
+ |---|---|
73
+ | **"Remember how I like to work."** | Global preference notes, available to main Pi and Jarvis across projects |
74
+ | **"We already decided this."** | Project-scoped decisions and corrections that survive session changes |
75
+ | **"Jarvis found something useful."** | A saved fact can be recalled later in main Pi without enabling `Note main` or `Redirect` |
76
+ | **"What did we say about deployment?"** | Keyword search across saved notes and bounded conversation captures |
77
+ | **"Show me the original tool output."** | Separately enabled archive search, session provenance and paged raw entries |
78
+ | **"I have months of existing Pi chats."** | Explicit bulk-import preview, confirmation, duplicate skipping and per-file reports |
61
79
 
62
- - checking what the main agent is doing right now
63
- - seeing what changed since the last `/jarvis` turn
64
- - asking for triage, summaries, or a second opinion
65
- - inspecting the repo with local tools when you turn them on
66
- - sending a non-interrupting note back to the main session
67
- - redirecting the main session only after explicit confirmation
80
+ Memory is **context, not authority**: records can be stale, recall is bounded and relevance-based, and model curation depends on the model using its tools. Current instructions still win. Archive search covers recorded or explicitly imported history—not everything Pi has ever seen.
68
81
 
69
- > Think of it as a side conversation with real context, not a detached scratchpad.
82
+ ### Memory in 60 seconds
70
83
 
71
- ### Typical prompts
84
+ After installing and reloading, check the first-use notice and effective settings. These are **literal commands**, not promises that a model will save or recall a fact:
85
+
86
+ ```text
87
+ /jarvis-memory
88
+ /jarvis-memory remember Build workflow | This project uses npm, not pnpm.
89
+ /jarvis-memory remember --global Answer style | Prefer concise answers with file paths.
90
+ /jarvis-memory search Build workflow
91
+ ```
92
+
93
+ The first note stays in this project; the second is a deliberate cross-project preference. Both lanes use the same store. Inside the overlay, `/memory search Build workflow` runs locally without a model call or waiting for queued side work.
94
+
95
+ Now ask either lane: *"What build workflow did we save for this project? Search memory if needed."* Or ask: *"Find the earlier discussion about deployment and show the source before suggesting a change."* Automatic recall uses global/current-project records; broader search is explicit:
96
+
97
+ ```text
98
+ /jarvis-memory search --all deployment
99
+ ```
100
+
101
+ **Your controls, immediately available:** `/jarvis-memory off` is the global master-off; `/jarvis-memory --project off` pauses this project. `/jarvis-memory --project capture off` and `--project recall off` control saving and recall separately here. Full off retains data but blocks even record inspection; none of these switches erases original Pi transcripts or already-sent model context. [Inspect, edit and forget saved records](#inspect-edit-and-forget).
102
+
103
+ ### A second cockpit—not a second task queue for main Pi
104
+
105
+ Use `/jarvis` for a second opinion, progress checks or repo inspection while the main lane stays on its plan. Repo tools, `Note main` and `Redirect` are separate opt-ins; redirects still require confirmation. Shared memory does **not** steer, interrupt or queue work into the other lane.
72
106
 
73
107
  - *"What is the main agent doing right now?"*
108
+ - *"Which project decisions did we save, and which might be stale?"*
74
109
  - *"Summarize the last validation failure and tell me what matters."*
75
110
  - *"Check this file while the main session keeps moving."*
76
- - *"Compare what changed since my last `/jarvis` turn."*
77
111
  - *"Redirect the main session, but make me confirm it first."*
78
112
 
79
113
  ---
@@ -86,11 +120,12 @@ The main Pi session should stay on the critical path.
86
120
  | **What it keeps** | Curated notes plus bounded finalized user/assistant text captures | Complete accepted finalized Pi journal entries, with provenance and paged raw reads |
87
121
  | **Default** | **On in trusted projects**, with separate capture/recall controls | **Off**; recording and model access are separately controlled |
88
122
  | **Retrieval** | Automatic recall from global/current-project memory; explicit broader search | Local indexed search and session browsing; no automatic context injection |
123
+ | **Storage** | Local plaintext SQLite | Plaintext by default; optional password encryption for the archive database, index and SQLite journals |
89
124
  | **Manage it** | `/jarvis-memory` · overlay `/memory` | `/jarvis-archive` · overlay `/archive` |
90
125
 
91
126
  Both work across main Pi and Jarvis, independently of **Repo tools** and whether the overlay is open. Each has its own local SQLite store and global/project controls. Turning one off does not turn the other off.
92
127
 
93
- **Privacy matters:** storage is local plaintext. Archive content is unredacted and can include secrets; granting model access can send retrieved content to your model provider. “Full” means accepted finalized data exposed by Pi—not hidden provider reasoning or a crash-safe audit log. Historical import is explicit. See the [memory controls](#shared-memory) and [archive limits](#full-session-archive) before enabling more access.
128
+ **Privacy matters:** shared memory remains local plaintext. The archive also defaults to plaintext, with separate, [optional password encryption](#optional-archive-encryption). Archive content is unredacted and can include secrets; encryption does not prevent authorized model reads from sending retrieved content to your provider. It does not protect original Pi transcripts, shared memory or retained plaintext backups. “Full” means accepted finalized data exposed by Pi—not hidden provider reasoning or a crash-safe audit log. Historical import is explicit. Review the [memory controls](#shared-memory), [archive limits](#full-session-archive) and encryption boundary before enabling more access.
94
129
 
95
130
  ---
96
131
 
@@ -98,8 +133,9 @@ Both work across main Pi and Jarvis, independently of **Repo tools** and whether
98
133
 
99
134
  | Capability | What you get |
100
135
  |---|---|
101
- | **Shared memory** | Main Pi and Jarvis remember useful discussions across sessions; enabled by default, with global/project controls and a master off switch |
136
+ | **Shared persistent memory** | One store for main Pi + Jarvis: reusable preferences, decisions and bounded finalized conversations; on in trusted projects, with global/project controls and a master off switch |
102
137
  | **Optional full-session archive** | Off by default; raw finalized entries, local indexed cross-session search, separate model permission, and preview-confirmed bulk history import |
138
+ | **Optional archive encryption** | Off by default; password-protected database/index/journals, explicit migration and cleanup, and selectable unlock lifetimes |
103
139
  | **Persistent side lane** | `/jarvis` keeps its own isolated conversation state and restores prior side-session history |
104
140
  | **Live awareness** | Jarvis sees the current main-session summary plus a delta since the last `/jarvis` turn |
105
141
  | **Permission-gated tools** | Local `read`, `bash`, `edit`, `write`, and configured native MCP stay off until you enable Repo tools |
@@ -177,9 +213,9 @@ Requires **Pi 1.0.0** and **Node.js 22.19.0 or newer**. Version **1.6.0** suppor
177
213
  ### 2) Restart or reload Pi
178
214
 
179
215
  `pi install` registers the package automatically. For local development, build and load `./dist/index.js` with `pi -e ./dist/index.js`.
180
- **New in 1.7.0: shared memory is enabled by default in trusted projects**, including main Pi even if you never open the overlay. A first-use notice explains capture and recall. Already using another memory extension? Run `/jarvis-memory off` before your first prompt; this disables both main and Jarvis memory without deleting anything.
216
+ **Shared memory is enabled by default in trusted projects**, including main Pi even if you never open the overlay. A first-use notice explains capture and recall; [try the one-minute memory workflow](#memory-in-60-seconds). Already using another memory extension? Run `/jarvis-memory off` before your first prompt; this disables both main and Jarvis memory without deleting anything.
181
217
 
182
- **New in 1.8.0: the separate full-session archive is OFF by default.** Nothing is imported or recorded by that subsystem until you opt in. See [Full-session archive](#full-session-archive).
218
+ **The separate full-session archive is OFF by default.** Nothing is imported or recorded by that subsystem until you opt in. **Optional password encryption is also OFF by default**; installation does not encrypt an existing archive or change your recording/model/memory settings. If you want to avoid new plaintext archive captures during setup, pause effective **capture before enabling or migrating**. See [Full-session archive](#full-session-archive) and [safe encryption setup](#safe-initial-setup).
183
219
 
184
220
  ### 3) Open Jarvis
185
221
 
@@ -235,7 +271,7 @@ Removes the selected scope so `/jarvis` thinking falls back through the remainin
235
271
  Reports shared-memory status. Use `/jarvis-memory help` for controls and data-management commands. Memory controls default to **global**, unlike model/thinking controls. See [Shared memory](#shared-memory) below.
236
272
 
237
273
  ### `/jarvis-archive`
238
- Reports the separate full-session archive's status. It defaults **OFF**, with independent capture and model-access controls. `/jarvis-archive help` documents enablement warnings, paging, explicit import, and deletion. See [Full-session archive](#full-session-archive).
274
+ Reports the separate full-session archive's status. It defaults **OFF**, with independent capture, model-access and optional encryption controls. `/jarvis-archive help` documents enablement warnings, paging, explicit import, deletion and human-only encryption administration. See [Full-session archive](#full-session-archive).
239
275
 
240
276
  ### Side-session commands inside `/jarvis`
241
277
  The `/jarvis` input handles a small set of built-in commands against the isolated side-session:
@@ -256,6 +292,8 @@ This is a **separate, optional subsystem**, not a change to shared memory's cura
256
292
 
257
293
  ### Enable only after reviewing the risks
258
294
 
295
+ These examples opt into recording; they are **not encrypted-first setup**. If you want to avoid new plaintext archive captures, [pause effective capture before enabling or migrating](#safe-initial-setup), then verify encryption/cleanup before explicitly resuming capture.
296
+
259
297
  ```text
260
298
  /jarvis-archive # status; no archive-record reads
261
299
  /jarvis-archive --project on --confirm-sensitive # record here only
@@ -272,7 +310,7 @@ Controls default to **global**; use `--project` for an override. Resolution is p
272
310
  - Project: `.pi/jarvis-archive.json`
273
311
  - Shape: `{ "archive": { "enabled": true, "capture": true, "modelAccess": false } }`
274
312
 
275
- Enabling/model-access commands require the literal warning acknowledgment, and direct-file enablement shows a first-use warning. **This archive is unredacted plaintext and may retain passwords, tokens, private files, and sensitive tool output.** Model access can send retrieved data to the active provider. It is not a sandbox, encryption mechanism, or a substitute for carefully managing secrets.
313
+ Enabling/model-access commands require the literal warning acknowledgment, and direct-file enablement shows a first-use warning. **This archive is unredacted, PLAINTEXT by default, and may retain passwords, tokens, private files, and sensitive tool output.** Optional password encryption protects only its active database, index and SQLite journals; original Pi transcripts, shared memory and retained plaintext sources/backups remain outside that protection. Model access can send retrieved data to the active provider even when storage is encrypted. Neither mode is a sandbox or a substitute for carefully managing secrets. Review [safe encryption setup](#safe-initial-setup) **before** enabling if you want to avoid new plaintext archive captures.
276
314
 
277
315
  ### What “full” means
278
316
 
@@ -344,13 +382,105 @@ Bulk import is a human command, not a model tool. It requires enabled recording
344
382
 
345
383
  Single-file import is **human-only**, requires enabled recording and an explicit regular v3 JSONL file, and preserves the source header's project/session identity—even if different from the current project. Directory discovery happens only through the explicit bulk preview above; no silent historical import occurs. Both import modes require v3 session files; legacy session versions require a separately reviewed conversion first. Completed entries survive a partial/cancelled import, with counts reported; duplicate entries are skipped, differing payloads for an existing identity are rejected, and originals are never modified. Deletion defaults to this project; `--all` is explicit. Stable identity tombstones prevent re-import of deleted entries, not every semantic copy or other previously unarchived entry.
346
384
 
347
- Storage is lazy SQLite under `<active-agent-dir>/extensions/pi-jarvis-archive/archive.sqlite`, defaulting to `~/.pi/agent/extensions/pi-jarvis-archive/archive.sqlite`. Owned directories/files use private permissions where supported, with defensive link/type checks and concurrent-writer transactions. There is no background watcher: observed settings changes are propagated between mounted lanes, while other processes recheck at operation boundaries. Deletion does not erase original Pi files, prior search-result copies, already-sent model context or backups, and does not guarantee reclaimed disk space or forensic erasure. For a complete reset, stop all Pi processes using the store and remove only its archive directory yourself; that also removes tombstones. Shared memory stays separate and unchanged. To stop both Jarvis persistence layers, use both `/jarvis-archive off` and `/jarvis-memory off`; neither disables Pi's original session transcripts.
385
+ Storage is lazy SQLite under `<active-agent-dir>/extensions/pi-jarvis-archive/`: the plaintext default uses `archive.sqlite` (normally `~/.pi/agent/extensions/pi-jarvis-archive/archive.sqlite`). After explicit encryption management, `archive.vault.json` selects a generation at `vaults/<UUID>/archive.sqlite`; the same root retains prior generations until explicit cleanup. Owned directories/files use private permissions where supported, with defensive link/type checks and concurrent-writer transactions. There is no background watcher: observed settings changes are propagated between mounted lanes, while other processes recheck at operation boundaries. Deletion does not erase original Pi files, prior search-result copies, already-sent model context or backups, and does not guarantee reclaimed disk space or forensic erasure. For a complete reset, stop all Pi processes using the store and remove only its archive directory yourself; that also removes tombstones. Shared memory stays separate and unchanged. To stop both Jarvis persistence layers, use both `/jarvis-archive off` and `/jarvis-memory off`; neither disables Pi's original session transcripts.
386
+
387
+ ---
388
+
389
+ ## Optional archive encryption
390
+
391
+ Version **1.10.0** provides **optional, OFF-by-default password encryption** for the full-session archive. It is **agent-wide**, shared by main Pi and Jarvis in the same active agent directory, not a project-scoped setting. Encryption is independent of archive enablement, capture, model access, shared memory, Repo tools and bridge permissions. No archive is automatically migrated, no history is backfilled, and no user setting is changed automatically.
392
+
393
+ ### What it protects—and what it does not
394
+
395
+ Encrypted operation protects the **active archive SQLite database, its FTS search index and SQLite journal/WAL content**, not just message bodies. A random 256-bit data key is password-wrapped with scrypt and AES-256-GCM; the database uses a SQLCipher-4-compatible AES-256-CBC/HMAC-SHA512 profile provided by SQLite3MultipleCiphers. Ordinary encrypted operation does not use a temporary plaintext database; temporary SQLite work is memory-only.
396
+
397
+ It does **not** encrypt Pi's original JSONL/session files, shared-memory SQLite, external attachments, exports, independently retained backups, or previously retrieved/provider-sent context. **Migration retains its source, including plaintext, until explicit cleanup.** Vault metadata (generation identities, wrapping parameters and startup policy) and filesystem metadata are not concealed. An unlocked process and authorized tools can read the contents; swap, core dumps, trusted extensions and malicious same-user code are outside this boundary. There is **no independently audited cryptography, official/vendor-audited SQLCipher, FIPS, sandbox or forensic-erasure claim**. Public/private-key unlocking is deferred.
398
+
399
+ Choose a strong, unique password and keep it safely outside Pi conversation history. Passwords are valid Unicode, **1–4096 UTF-8 bytes**, without control characters or line breaks; they are not trimmed or normalized. There is no password-recovery bypass. `/jarvis-archive password` requires an unlocked archive, asks for a new password twice, and locks afterward. It **rewraps the same data key, not key rotation**: old key/envelope backups may still unlock that key's data.
400
+
401
+ ### Safe initial setup
402
+
403
+ These are **explicit user actions**, not permission for an agent or extension to change your settings.
404
+
405
+ 1. Start Pi yourself in **regular TUI**: `pi --tui-mode regular`. Stop **all other Pi instances using this agent directory**, including older versions, before migration, recovery or cleanup. Review available disk space: migration retains both source and target.
406
+ 2. Run `/jarvis-archive status` and review the configured/effective enablement, capture and model-access settings, trust and any config errors. Project fields override global defaults; an explicit global archive `off` is a master-off. Repair malformed settings manually without discarding privacy controls.
407
+ 3. **If avoiding new plaintext archive captures, pause CAPTURE before enabling or migrating**, for example `/jarvis-archive --project capture off`, then check status for effective **capture off**. A global `capture off` alone does not defeat project `capture on` overrides. Review every scope you intend to enable; do not start sensitive work until the effective pause is confirmed. This pause does not stop Pi's own transcripts or shared-memory capture.
408
+ 4. Enable the archive only in your intended scope, for example `/jarvis-archive --project on --confirm-sensitive`, and confirm that it is configured **ON in a trusted project with capture still off**. Project `on` cannot override an explicit global master-off; choose any global change yourself, recognizing that global enablement can affect other projects. Encryption administration requires enabled/trusted archive policy, but **does not require capture or model access to be on**. Leave model access off unless you separately want it.
409
+ 5. Run `/jarvis-archive encryption on --confirm-sensitive --confirm-stopped`. Enter the new password twice in the private prompt, verifying **each** submission as described below. On success the encrypted generation is unlocked for the current main session; your capture setting is unchanged. Inspect `/jarvis-archive encryption status` and, if desired, manually inspect records with capture/model access still off. A pre-existing archive's accepted records are migrated exactly; old Pi session files are not imported.
410
+ 6. Verify that the active encrypted archive is usable **before deleting its retained source**. If you choose to remove retired plaintext, run `/jarvis-archive encryption cleanup --confirm-sensitive --confirm-stopped` with a live unlock. Cleanup ends the local grant: unlock again, check status/retired plaintext counts and inspect any reported partial cleanup. Do not call the archive protected while plaintext copies you care about still remain. Cleanup does not touch outside backups or original transcripts.
411
+ 7. **Resume capture explicitly only when ready**, in the scope you paused, for example `/jarvis-archive --project capture on`; check effective status again. Unlocking and migration do not turn capture on or recover the paused period. Enable model access separately only if intended.
412
+
413
+ ### Human commands
414
+
415
+ These commands run locally without a provider call and are **not model tools**. No password, key, path or scope arguments are accepted. The overlay's `/archive …` alias also works locally; password entry closes Jarvis and uses the main editor area, revoking the overlay's transient permissions.
416
+
417
+ ```text
418
+ /jarvis-archive encryption [status]
419
+ /jarvis-archive encryption on --confirm-sensitive --confirm-stopped
420
+ /jarvis-archive encryption off --confirm-sensitive --confirm-stopped
421
+ /jarvis-archive encryption cleanup --confirm-sensitive --confirm-stopped
422
+ /jarvis-archive encryption recover --rollback --confirm-sensitive --confirm-stopped
423
+ /jarvis-archive encryption break-lock --confirm-sensitive --confirm-stopped
424
+ /jarvis-archive unlock [session|process|remember|for MINUTES|idle MINUTES]
425
+ /jarvis-archive lock
426
+ /jarvis-archive password
427
+ /jarvis-archive startup manual|prompt|remember
428
+ ```
429
+
430
+ **`encryption on` migrates the active archive to an encrypted generation; `encryption off` converts it to plaintext. Neither turns recording on/off.** In contrast, `/jarvis-archive off` is the ordinary archive master-off: it pauses reads/capture without decrypting or deleting stored files. `lock` revokes the local key first and then attempts durable remembered-authorization revocation; a failure is reported honestly, not silently repaired. Other processes observe durable revisions at operation boundaries, not instantaneously.
431
+
432
+ ### Private password entry
433
+
434
+ **Only Pi regular TUI is supported** (`pi --tui-mode regular`). Fullscreen, unknown/missing renderer modes and non-TUI operation refuse password entry; there is no ordinary-editor, RPC, argument or environment fallback. Do not change renderer settings automatically. Passwords are masked and never routed through normal editors/history, model tools, session entries, notifications or logs.
435
+
436
+ **Every submit or cancel—including typed-only Enter, Escape and Ctrl+C—requires a fresh displayed code typed by hand, followed by Enter.** Pasting a code cannot approve completion. Cancellation immediately revokes backend work, but retains a **cancel-only private input sink** until you verify its exit; a completed/aborted backend promise does not restore the editor. Jarvis, its model picker and main-memory review cannot overlap that ownership. Cancellable main-session switch/fork/tree navigation is refused until verified exit; retry navigation afterward. Resize a tiny terminal if the code is not readable. Repeated hostile input can deny service; this is not proof that every buffered transport byte has drained.
437
+
438
+ **Do not force `/reload`, quit or focus replacement while entering a password.** Forced host reload/quit and trusted external focus replacement cannot preserve input quarantine. The extension abandons ownership and wipes/revokes what it owns without stale editor-restoration callbacks, but cannot protect bytes routed after host/process teardown or genuine human-verified release. Trusted extensions with input/screen/process access are not isolated. Use the displayed verified cancellation instead.
439
+
440
+ ### Unlock lifetimes and startup
441
+
442
+ | Choice | Behavior |
443
+ |---|---|
444
+ | `unlock` / `unlock session` | Default. Main-session-owned grant shared with Jarvis; overlay close and side `/new` do not end it. Replacing the main session ends it. |
445
+ | `unlock process` | Process-local grant; supported main `new`/`resume`/`fork` handoffs preserve it. Reload, quit and process restart end it. |
446
+ | `unlock for MINUTES` | Fixed-duration grant, 1–10080 integer minutes. Handoff preserves the original deadline. |
447
+ | `unlock idle MINUTES` | Locks after that many minutes without successful archive data activity. Status/policy checks do not refresh it; handoff preserves the deadline. |
448
+ | `unlock remember` | Explicitly saves the random data key—not the password—in the OS credential store and selects `startup remember`. Persistent-local grant can be restored on later permitted main startup. |
449
+ | `startup manual` | Default. No automatic prompt/credential restore; clears remembered authorization and locks the local grant. |
450
+ | `startup prompt` | Clears remembered authorization and locks locally; later permitted main startup requests a password for a session grant. Requires regular TUI. |
451
+ | `startup remember` | Requires an already unlocked encrypted archive; explicitly authorizes OS-backed restoration. |
452
+
453
+ Timed grants check both monotonic and wall time, including access-boundary expiry after suspend/delayed timers; no immediate erasure during sleep is promised. **Plaintext conversion refuses fixed/idle timed grants before copying a key or publishing a transition**: explicitly `unlock session` or `unlock process` first if you really intend conversion. Any grant can be revoked by explicit lock, observed full-off/trust/config failure, revision changes or unsafe storage. No instantaneous cross-process key erasure is promised.
454
+
455
+ Startup runs only from the **main** lifecycle, never Jarvis boot. Full-off, untrusted/malformed policy and restart-required storage suppress prompts, credential access and database authentication. Restoring trust does not silently reuse a revoked local grant. An explicit nonremember unlock clears an existing remembered authorization (and changes remembered startup to manual); a startup manual/prompt selection also clears it. Explicit lock clears remembered authorization durably before best-effort native credential deletion. Failed deletion can leave a key in the OS store and is reported; durable revocation is not a promise that all OS copies are erased.
456
+
457
+ ### Migration, cleanup and recovery
458
+
459
+ Migration uses a distinct generation, verifies exact stored raw JSON spelling, index text, provenance, row IDs and tombstones, and checks/checkpoints/closes/fsyncs the target before publication. Capture pauses without buffering or backfill. The source becomes a retired generation, **not automatically deleted**. At most **eight retired generations** are tracked; further migration requires explicit cleanup. Check status for retained **plaintext** generations. There is no hard total-disk quota.
460
+
461
+ Cleanup deletes only recognized retired SQLite files under the owned layout, never the active database or outside backups. It preflights files, deletes auxiliaries before the main file, and rechecks live authorization between deletions. Encrypted cleanup needs a live lease and authentication of the **existing active database**; a missing active database is not recreated. Failure can leave a **partial retained backup**; inspect the report/metadata, do not assume rollback or automatic deletion retry. Cleanup ends the local lease.
462
+
463
+ A pending Transition blocks archive reads, capture, import and ordinary deletion. `recover --rollback` is an explicit source-checked rollback, not a retry/resume of migration: it can discard only the known unpublished target. **A missing/empty/unsafe/changed known source requires manual inspection/restoration; preserve the target and metadata as potential copies.** An explicitly originally absent legacy source is different from a lost source. Never publish a missing known source as an empty archive or delete its possible remaining target. Invalid metadata requires manual inspection; it is not repaired automatically.
464
+
465
+ Locks are cooperative, not a filesystem sandbox. `break-lock` never steals a live or unknown lock: it requires a demonstrably dead local PID on the same host plus identity/token rechecks. The confirmation flags acknowledge that other Pi instances have actually been stopped; they do not stop them for you.
466
+
467
+ **Uncertain native close, publication or lock release requires stopping Pi, inspecting status/storage and an actual Pi process restart before further access or recovery.** `/reload`, new sessions, aliases and logical quit do not clear restart-required state. Publication may already have succeeded even if an operation reported failure: never assume a guaranteed Transition, replay an uncertain write or automatically retry cleanup/recovery. Restart clears the process-local safety block, not invalid metadata, missing sources or a durable Transition; inspect again and choose recovery explicitly.
468
+
469
+ ### Dependencies and platform limits
470
+
471
+ Encryption lazily loads exact optional **`better-sqlite3-multiple-ciphers@13.0.3`**; plaintext uses `node:sqlite`. Remembered unlock separately needs exact optional **`@napi-rs/keyring@2.1.0`** and an available, authorized OS credential service. On Linux this is explicitly **Secret Service**, with no kernel-keyring downgrade; macOS/Windows use the adapter's native OS stores. A headless/locked/unavailable service can refuse remembered unlock. Manual password unlock does not require remembered-key storage.
472
+
473
+ Linux glibc prebuilt bindings require **glibc 2.35 or newer**. Upstream advertises musl/macOS/Windows bindings, but **local runtime validation is Linux-only**; other platforms and real OS credential integration are not certified by that validation. Missing, omitted or incompatible optional dependencies **fail closed**—no plaintext database, ordinary input, unprotected key file or alternative credential backend fallback. Runtime does not execute install scripts or auto-build/download replacement binaries. A failed remembered restore stays locked; manually choose a password unlock if desired.
474
+
475
+ See [Archive encryption design and operating contract](docs/archive-encryption-design.md) for the format, lifecycle and validation limits.
348
476
 
349
477
  ---
350
478
 
351
479
  ## Shared memory
352
480
 
353
- Main Pi and Jarvis use **one local memory service**, independent of the overlay lifecycle. Useful Jarvis discussions can inform a later main session and vice versa—even when `Note main` is off. Memory does not steer or queue messages into the other session; it supplies historical context when recalled. Close/reopen, `/new`, and project changes do not erase it.
481
+ **The feature you can use even without the overlay:** main Pi and Jarvis use **one local memory service**, independent of the overlay lifecycle. Useful Jarvis discussions can inform a later main session and vice versa—even when `Note main` is off. Memory does not steer or queue messages into the other session; it supplies historical context when recalled. Close/reopen, `/new`, and project changes do not erase it.
482
+
483
+ Use project notes for architecture choices, build conventions, corrections and useful references. Use global notes only for preferences you deliberately want across projects. Prefer concise, specific facts with stable titles; search and inspect their dates/provenance before relying on them. **Do not use memory as a password or token store.** See [Memory in 60 seconds](#memory-in-60-seconds) for commands you can run without involving a model.
354
484
 
355
485
  ### What is remembered
356
486
 
@@ -599,10 +729,12 @@ Use narrowly scoped credentials and trust your configured servers. Enabling Repo
599
729
 
600
730
  ## Development
601
731
 
602
- Install dependencies:
732
+ Archive encryption is optional and off by default; its [design and operating contract](docs/archive-encryption-design.md) documents the shipped password-based feature and its limits. Development validation uses disposable synthetic archives and injected credential stores—never real user migrations or OS credentials. Keep optional native packages lazy, exact-pinned and fail-closed; public/private-key support remains deferred.
733
+
734
+ Install dependencies without running lifecycle scripts:
603
735
 
604
736
  ```bash
605
- npm install
737
+ npm install --ignore-scripts
606
738
  ```
607
739
 
608
740
  Type-check:
@@ -0,0 +1,55 @@
1
+ export declare const ARCHIVE_ENVELOPE_FORMAT = "pi-jarvis-archive-key";
2
+ export declare const ARCHIVE_ENVELOPE_VERSION = 1;
3
+ export declare const ARCHIVE_ENVELOPE_CIPHER = "sqlcipher4";
4
+ /** Version 1 supports exactly one password slot. Other slot kinds require a new version. */
5
+ export interface ArchiveKeyEnvelope {
6
+ readonly format: typeof ARCHIVE_ENVELOPE_FORMAT;
7
+ readonly version: typeof ARCHIVE_ENVELOPE_VERSION;
8
+ readonly vaultId: string;
9
+ readonly cipher: typeof ARCHIVE_ENVELOPE_CIPHER;
10
+ readonly passwordSlot: {
11
+ readonly kind: "password";
12
+ readonly kdf: {
13
+ readonly name: "scrypt";
14
+ readonly N: 131072;
15
+ readonly r: 8;
16
+ readonly p: 1;
17
+ };
18
+ readonly wrapCipher: "aes-256-gcm";
19
+ readonly salt: string;
20
+ readonly nonce: string;
21
+ readonly wrappedKey: string;
22
+ readonly tag: string;
23
+ };
24
+ }
25
+ export type ArchiveCryptoErrorCode = "INVALID_ENVELOPE" | "INVALID_PASSWORD" | "INVALID_KEY" | "UNLOCK_FAILED" | "CRYPTO_FAILED" | "BUSY" | "ABORTED";
26
+ /** Fixed messages/codes only: never includes passwords, envelope data, native errors or causes. */
27
+ export declare class ArchiveCryptoError extends Error {
28
+ readonly code: ArchiveCryptoErrorCode;
29
+ constructor(code: ArchiveCryptoErrorCode);
30
+ }
31
+ /**
32
+ * Accepts an already-decoded JSON object, not JSON text. Returns a detached validated snapshot.
33
+ * A JSON loader must enforce its own size/duplicate-member limits before decoding; duplicates
34
+ * cannot be recovered from an object after JSON.parse. No getters/proxies or extra fields accepted.
35
+ */
36
+ export declare function parseArchiveEnvelope(input: unknown): ArchiveKeyEnvelope;
37
+ /**
38
+ * Generates a random archive DEK, independent of the password. Caller owns/wipes the returned key.
39
+ * AbortSignal is checked before/after work; Node scrypt cannot be interrupted once started.
40
+ * Buffer wiping is best effort, not forensic erasure of JS strings or native/runtime copies.
41
+ */
42
+ export declare function createArchiveEnvelope(password: string, signal?: AbortSignal): Promise<{
43
+ envelope: ArchiveKeyEnvelope;
44
+ key: Buffer;
45
+ }>;
46
+ /** Wrong passwords, malformed/tampered envelopes and native crypto failures share one safe error. */
47
+ export declare function unlockArchiveEnvelope(input: unknown, password: string, signal?: AbortSignal): Promise<Buffer>;
48
+ /**
49
+ * PRECONDITION: caller supplies this vault's previously validated, unlocked DEK. Without the old
50
+ * password this function cannot prove a key matches the old envelope. Passing a wrong key makes
51
+ * the new envelope unusable for the existing archive. Does not validate/re-encrypt archive payloads.
52
+ * Preserves vaultId/cipher; generates a new salt/nonce. Never wipes/mutates the caller-owned key.
53
+ */
54
+ export declare function rewrapArchiveEnvelope(input: unknown, key: Buffer, newPassword: string, signal?: AbortSignal): Promise<ArchiveKeyEnvelope>;
55
+ //# sourceMappingURL=archive-crypto.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"archive-crypto.d.ts","sourceRoot":"","sources":["../archive-crypto.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,uBAAuB,0BAA0B,CAAC;AAC/D,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAC1C,eAAO,MAAM,uBAAuB,eAAe,CAAC;AAUpD,4FAA4F;AAC5F,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,MAAM,EAAE,OAAO,uBAAuB,CAAC;IAChD,QAAQ,CAAC,OAAO,EAAE,OAAO,wBAAwB,CAAC;IAClD,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,OAAO,uBAAuB,CAAC;IAChD,QAAQ,CAAC,YAAY,EAAE;QACtB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;QAC1B,QAAQ,CAAC,GAAG,EAAE;YAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;YAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;YAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;YAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAA;SAAE,CAAC;QAC5F,QAAQ,CAAC,UAAU,EAAE,aAAa,CAAC;QACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;QAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;KACrB,CAAC;CACF;AAED,MAAM,MAAM,sBAAsB,GAC/B,kBAAkB,GAAG,kBAAkB,GAAG,aAAa,GACvD,eAAe,GAAG,eAAe,GAAG,MAAM,GAAG,SAAS,CAAC;AAW1D,mGAAmG;AACnG,qBAAa,kBAAmB,SAAQ,KAAK;IAChC,QAAQ,CAAC,IAAI,EAAE,sBAAsB;gBAA5B,IAAI,EAAE,sBAAsB;CAIjD;AA4CD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,kBAAkB,CAwBvE;AA+DD;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,kBAAkB,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAoB1I;AAED,qGAAqG;AACrG,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CA8BnH;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAsB/I"}