You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
skills/okfmem-curate/SKILL.md Phase 1 derives the memory dir by hand-rolling the project slug:
# skills/okfmem-curate/SKILL.md:54-56# project slug = absolute cwd with / replaced by -
SLUG=$(pwd -P | sed 's|/|-|g')
MEM_DIR="$HOME/.claude/projects/$SLUG/memory"
This reimplements memory_init.encode_root — badly — and is wrong in two ways.
1. It eats the drive colon on Windows
encode_root encodes both the separator and the drive colon: C:\Users\you\okfmem → C--Users-you-okfmem (the : becomes the second dash). The sed
above replaces only /, so on a Windows checkout it produces a slug that does not match any
directory under ~/.claude/projects/. Phase 1's own guard then fires — "If $MEM_DIR doesn't
exist, tell the user and stop" — so /okfmem-curatecannot run at all on Windows unless
the user passes an explicit path argument every time. Silent-ish (it reports a missing dir),
but the reported cause is wrong: the dir exists, the slug is.
This is the same drive-colon-shape footgun documented across the repo's Windows work
(#14/#16/#17, #41, #42) — a hand-rolled separator swap standing in for encode_root.
2. It ignores project renames
encode_root is only half the resolution. The registry (~/okfmem-store/registry.json) maps a
repo root to its store project name, which honours renames and per-project overrides. A raw
cwd-to-slug transform can't see any of that, so a renamed project resolves to a stale or
missing directory even on POSIX, where the sed is otherwise correct.
Fix
okfmem init --project-link-state already exists (shipped #48) as the shared read-only probe
for exactly this question. It returns one of linked <name> / unlinked <name> / not-a-repo / no-claude, resolves the name through the registry, and never re-derives the
encoded path in shell. skills/okfmem-save/SKILL.md Step 1 already uses it — this is a
straight port of that block, and it kills the sed for the same stated reason.
Replace Phase 1's derivation with:
# Ask the engine, rather than re-deriving the encoded path: `encode_root` also# encodes the drive colon on Windows, so a hand-rolled sed resolves to the wrong dir.
LINK_STATE="$(okfmem init --project-link-state)"# linked <name> | unlinked <name> | not-a-repo | no-claude
STORE="${OKFMEM_STORE:-$HOME/okfmem-store}"
MEM_DIR="$STORE/projects/$(echo "$LINK_STATE"| awk '{print $2}')"
and give each non-linked state a specific message rather than the generic
"$MEM_DIR doesn't exist":
State
What Phase 1 should say
linked <name>
proceed
unlinked <name>
this repo has no memory link — run okfmem init from the repo root, then re-run
not-a-repo
cd to the project root first
no-claude
the harness isn't installed; nothing to curate
Keep the existing behaviour that an explicit path argument overrides everything — that is
the escape hatch that made this bug survivable, and audit <path> depends on it.
Phase 1's symlink-detection step (readlink "$MEM_DIR") is unaffected and stays as-is.
Acceptance criteria
skills/okfmem-curate/SKILL.md Phase 1 no longer contains pwd -P | sed; it resolves MEM_DIR via okfmem init --project-link-state.
The resolved path is correct on Windows (drive colon encoded) — verified against encode_root, not against a hand-typed expectation.
A renamed project resolves through the registry to its current store project name.
Each of the four probe states has its own message; unlinked names okfmem init as the
remedy rather than reporting a missing directory.
An explicit path argument still overrides the probe (/okfmem-curate audit <path> works
outside a repo).
python3 scripts/check-leaks.py exits 0 — the snippet uses ~/okfmem-store / $OKFMEM_STORE, never a real home path.
Notes for the implementer
This is a skill-text change, not engine code — no new Python, no new subcommand. The probe
it calls already ships.
Problem
skills/okfmem-curate/SKILL.mdPhase 1 derives the memory dir by hand-rolling the project slug:This reimplements
memory_init.encode_root— badly — and is wrong in two ways.1. It eats the drive colon on Windows
encode_rootencodes both the separator and the drive colon:C:\Users\you\okfmem→C--Users-you-okfmem(the:becomes the second dash). Thesedabove replaces only
/, so on a Windows checkout it produces a slug that does not match anydirectory under
~/.claude/projects/. Phase 1's own guard then fires — "If$MEM_DIRdoesn'texist, tell the user and stop" — so
/okfmem-curatecannot run at all on Windows unlessthe user passes an explicit path argument every time. Silent-ish (it reports a missing dir),
but the reported cause is wrong: the dir exists, the slug is.
This is the same drive-colon-shape footgun documented across the repo's Windows work
(#14/#16/#17, #41, #42) — a hand-rolled separator swap standing in for
encode_root.2. It ignores project renames
encode_rootis only half the resolution. The registry (~/okfmem-store/registry.json) maps arepo root to its store project name, which honours renames and per-project overrides. A raw
cwd-to-slug transform can't see any of that, so a renamed project resolves to a stale or
missing directory even on POSIX, where the
sedis otherwise correct.Fix
okfmem init --project-link-statealready exists (shipped #48) as the shared read-only probefor exactly this question. It returns one of
linked <name>/unlinked <name>/not-a-repo/no-claude, resolves the name through the registry, and never re-derives theencoded path in shell.
skills/okfmem-save/SKILL.mdStep 1 already uses it — this is astraight port of that block, and it kills the
sedfor the same stated reason.Replace Phase 1's derivation with:
and give each non-
linkedstate a specific message rather than the generic"
$MEM_DIRdoesn't exist":linked <name>unlinked <name>okfmem initfrom the repo root, then re-runnot-a-repocdto the project root firstno-claudeKeep the existing behaviour that an explicit path argument overrides everything — that is
the escape hatch that made this bug survivable, and
audit <path>depends on it.Phase 1's symlink-detection step (
readlink "$MEM_DIR") is unaffected and stays as-is.Acceptance criteria
skills/okfmem-curate/SKILL.mdPhase 1 no longer containspwd -P | sed; it resolvesMEM_DIRviaokfmem init --project-link-state.encode_root, not against a hand-typed expectation.unlinkednamesokfmem initas theremedy rather than reporting a missing directory.
/okfmem-curate audit <path>worksoutside a repo).
python3 scripts/check-leaks.pyexits 0 — the snippet uses~/okfmem-store/$OKFMEM_STORE, never a real home path.Notes for the implementer
it calls already ships.
okfmem-savewas alreadyported on feat(init): seed store project on init + nag unwired repos on four surfaces #48; curate is the known remaining one, but a third would be the same bug.
CLAUDE.mdconfirmation discipline);nothing in this change touches that.