# Known Limitations & FAQ

[Back to README](../README.md)

## Known limitations (for now)

- Module-level injection state (`_injectedOnce`, `_turnCount`) is process-global. Safe for the standard single-user pi session; upgrade to a per-session Map if multi-session support is needed in future.
- Manual edits to `MEMORY.md` or `memory.jsonc` made between user prompts are picked up on the next user-prompt `before_agent_start` call (no cache to invalidate). This is by design.
- Atomicity is per file, not a multi-file transaction. Normal failed writes attempt rollback; abrupt termination can leave an unindexed topic or stale index metadata, and directory entries are not fsynced. OpenCode's explicit repair can recover shared unindexed topics, excluding tombstones; pin flags that lived only in a missing index cannot be recovered.
- The shared advisory protocol lacks atomic compare-and-unlink and does not protect against writers ignoring the lock. Use updated cooperating implementations on local filesystems.

## FAQ (post-0.3.0)

**Q: When does a threshold compaction automatically send `Continue.`?**
The fallback handoff-aware path only does so when the handoff has explicit unfinished-work language such as `need to`, `next step`, `pending`, `waiting for`, `not done`, `incomplete`, or `unfinished`. Ordinary completed prose containing words like `then`, `should`, or `next` does not trigger it. Set `auto_resume_after_threshold_compaction: true` in `memory.jsonc` to send `Continue.` after every threshold compaction regardless of the handoff.

Questions that came up while testing the `shared_dir` migration on an actual, already-populated install.

**Q: I just upgraded from a pre-0.3.0 version. Did anything of mine get deleted or overwritten?**
No. The config rename (`RULES.jsonc` → `memory.jsonc`) and the `shared_dir` carry-over are both strictly additive — they only ever create new files or copy existing ones. Nothing pre-existing is ever deleted, moved, or overwritten in place. See [First run: upgrading from a pre-0.3.0 install](shared-directory.md#first-run-upgrading-from-a-pre-030-install) for the exact file-by-file trace.

**Q: How do I check whether I'm currently opted in to `shared_dir`?**
Read the `shared_dir` value directly from `~/.pi/agent/memory.jsonc` — it's the only place this is configured, and it's always read fresh on every call (no caching). You can also infer it indirectly: if `~/.agents/memory/MEMORY.md` exists, `shared_dir` has been `true` at least once.

**Q: I opted in to `shared_dir`. Where did my memories go — are my old files gone?**
Your old files are untouched at `~/.pi/agent/memory/`. Opting in merges (never moves) `MEMORY.md` entries and topic files into `~/.agents/memory/`. `HANDOFF.md` is deliberately excluded — it always stays at `~/.pi/agent/HANDOFF.md`, since compaction handoff is a pi-only feature, not part of the shared cross-tool format.

**Q: I opted into `shared_dir` and another tool (e.g. openclaude-memory for opencode) already had memories in `~/.agents/memory/` — what happens to mine?**
They are merged in, not dropped. The carry-over appends any of your local entries whose topic file doesn’t already exist in the shared dir. If a filename collides with different content, your file is copied under a `-opim` suffix and that name is used in the appended index entry. If the content is identical, it’s a no-op — no duplicate is created. Nothing already in the shared dir is modified or deleted. See [Opting in when another tool already populated the shared dir](shared-directory.md#opting-in-when-another-tool-already-populated-the-shared-dir) for a full walkthrough.

**Q: If I opt in, then opt out, then opt in again — does everything stay in sync?**
**No — this is the biggest watch-out.** Toggling `shared_dir` is a one-time, one-directional migration, not a live sync:
- The carry-over from `~/.pi/agent/memory/` → `~/.agents/memory/` runs at most once, ever, guarded by a sentinel file (`~/.pi/agent/memory/.shared-dir-migrated`) written the moment the merge completes. Once that file exists, every future process start skips the merge entirely, even if you toggle `shared_dir` off and back on.
- There is **no reverse migration**. Opting out doesn't copy anything from `~/.agents/memory/` back to `~/.pi/agent/memory/` — it just changes which directory gets read/written going forward.
- This means the two directories can silently drift apart: writes made while `shared_dir: true` are invisible once you flip it back to `false`, and vice versa. Nothing is deleted, but whichever directory isn't currently active becomes a stale snapshot.

**What to do about it:** treat `shared_dir` as a deliberate one-way move, not a togglable setting you flip back and forth casually. If you do need to reconcile after toggling, diff `MEMORY.md` and the topic files between `~/.pi/agent/memory/` and `~/.agents/memory/` yourself and manually copy over whatever's missing — the extension will not do this for you.

**Q: What's `.shared-dir-migrated`, and can I delete it?**
It's an empty sentinel file the extension writes to `~/.pi/agent/memory/` the moment the `shared_dir` merge completes successfully. Its only job is to make every subsequent process start skip the merge in one `fs.existsSync` call instead of re-reading and re-comparing every local and shared file. Deleting it forces the merge to run again on the next process start — since the merge is additive and idempotent (identical content is always a no-op, collisions always resolve to the same `-opim` name), this is safe but pointless; there's no reason to delete it.

**Q: Does switching `shared_dir` also affect my `memory.jsonc` config, or my persist rules?**
No. `memory.jsonc` (config) and `HANDOFF.md` (compaction handoff) are fixed, pi-specific paths that are **never** affected by `shared_dir` — only the location of `MEMORY.md` and topic files changes. There's exactly one config file regardless of `shared_dir`'s value, so there's nothing to keep "in sync" on the config side — it's always already current.

**Q: What's `RULES.jsonc.bak` for, and can I delete it?**
It's a one-time safety backup of your legacy `RULES.jsonc`, created automatically the first time `memory.jsonc` was bootstrapped from it. It's inert afterward — nothing reads it again. Safe to keep indefinitely for peace of mind, or delete it once you've confirmed `memory.jsonc` has everything you expect.

**Q: I have two config files now (`memory.jsonc` and the old `RULES.jsonc`). Which one is active?**
`memory.jsonc` is the only one ever read after the initial migration. `~/.pi/agent/memory/RULES.jsonc` (and its `.bak`) are frozen historical snapshots from the migration moment — editing them does nothing. Always edit `~/.pi/agent/memory.jsonc`.

**Q: I edited `memory.jsonc` directly — will my changes get overwritten?**
No. `memory.jsonc` is only ever written by the extension when it doesn't exist yet (fresh install or first-time legacy fallback). Once it exists, the extension only reads it — your manual edits persist and take effect on the very next user prompt.

**Q: Does the shared directory lock/atomic-write behavior protect me from corruption if another tool writes to `~/.agents/memory/` at the same time?**
Yes, when the co-tenant honors current openclaude-memory conventions. Shared mutations and carry-over use a PID-aware lock, and index/topic writes are atomic. A busy shared store returns a retryable error rather than writing unlocked. This is same-user collaboration, not protection from a local process that ignores the lock or deliberately edits files.

**Q: Is the one-time `shared_dir` carry-over protected by that same lock?**
Yes. It acquires local then shared, skips both removal lists, and writes its sentinel only after success. A busy store retries on a later call. Startup recap retirement is separately locked; missing-index reads return an in-memory placeholder instead of bootstrapping an index outside the lock.

**Q: Why does a shared removal create `.ocl-removed`?**
OpenPI preserves topic files when removing an index entry. In the shared store it records that intentional removal using current openclaude-memory's `.ocl-removed` convention, preventing its repair command from re-indexing the file. Writing that topic again clears the tombstone.

**Q: Can two local sessions write at once?** Local mutations refuse contention after about 500 ms rather than waiting indefinitely or writing unlocked. Shared mode waits about 2 s and retries once after a 1 s delay. Retry busy results; each mutation retains its acquired directory if config changes during the wait.

**Q: Can a new topic overwrite an unrelated unindexed file?** No. Disk collisions are checked too. An unindexed regular file is reused only when its frontmatter name matches the requested topic; otherwise a free numeric suffix is selected.

**Q: Does replace keep an outdated description?** No. Both modes refresh name, description, and last-updated metadata, preserving creation and unrelated fields. Failed index publication attempts to restore the previous topic/index rather than silently leaving changed content after a reported failure.

**Q: Which co-tenant checks were run?** Version 0.3.11 passes 141 core tests and typecheck on pi 0.87.0 and 1.5.0, plus 15 extension checks on the floor and 17 on 1.5.0. Prior 134-check verification covered pi 0.99.1, 1.1.0, and 1.2.0. The lockfile dev baseline remains 1.2.0; CI covers all five versions. During v0.3.9 verification, the OpenCode sibling's real-process OpenCode/pi writer check also passed, preserving bodies, pins, removals, foreign entries, and cleanup; it was not rerun for the pi 1.5.0 assessment. Both implementations must be updated; older published versions may retain the audited unlocked startup paths.
