Reach projects under dotted paths, and let --cwd name the scope - #13
Conversation
Two defects that both made `ingest` lie quietly rather than fail. `mangle_cwd` replaced only `/`. The harness replaces every character outside `[A-Za-z0-9\-_]` — its own function is `e.replace(/[^a-zA-Z0-9\-_]/g,"-")` with `""` mapping to `unknown` — so a dot becomes a dash too. Engram therefore looked for `…construct-.claude-worktrees-x` where Claude Code had written `…construct--claude-worktrees-x`, and reported NOT_FOUND, which reads as "no such session" rather than "I spelled the directory wrong". Every worktree Claude Code creates lives under `.claude/worktrees/`, so this grew with use. The test planters carried a copy of the same wrong rule, which mattered more than it looks: a TempDir path contains `.tmpXXXX`, so after the fix they would have planted into a directory the reader no longer reads. Both now call one helper that mirrors production, with a comment saying why. `ingest --cwd` chose which transcripts to read but never the scope, which still resolved from the process's directory. Importing thirty-three projects from one terminal filed every one of them under whichever scope that terminal was in, and the response said `scope_origin: "git-root"` each time — correct-looking output for silently mis-filed data. `rules::resolve_scope_in` takes the directory as an argument; `resolve_scope` now delegates to it. Explicit `--scope` still wins. Verified on the real machine: the worktree that returned NOT_FOUND now yields 12 turns, and `--cwd /spacecraft-software/vault` files into `vault`. Gates: fmt, clippy -D warnings, 264 tests, REUSE 3.3, makeinfo clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016i16R4GhdSffsboRYq97Fs
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 29e4029917
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| .to_string_lossy() | ||
| .chars() |
There was a problem hiding this comment.
Match JavaScript’s UTF-16 replacement for astral characters
When the working-directory path contains a non-BMP character such as an emoji, iterating with Rust chars() replaces it with one dash, while Claude Code’s non-u JavaScript regex processes its two UTF-16 surrogate code units separately and produces two dashes. For example, Claude Code maps /tmp/😀 to -tmp---, but this function returns -tmp--, so the transcript directory is again reported as missing; iterate over UTF-16 code units (and update the mirrored test helper) to reproduce the harness exactly.
AGENTS.md reference: AGENTS.md:L261-L261
Useful? React with 👍 / 👎.
Two defects that both made
ingestlie quietly rather than fail. Found while working out how to bulk-import every session on a machine — both block that directly.1. A dotted path was unreachable, and said
NOT_FOUNDmangle_cwdreplaced only/. The harness replaces more. Its own function, from the Claude Code bundle:So a dot becomes a dash too, and the two spellings diverge:
Engram reported
NOT_FOUND, which reads as "no such session" rather than "I spelled the directory wrong". Every worktree Claude Code creates lives under.claude/worktrees/, so the blind spot grows with use.Verified against all 17 project directories on this machine and 46 OpenClaude ones — the new rule reproduces every name exactly.
The test planters carried a copy of the same bug
This mattered more than it looks.
plant_claude_transcriptandplant_openclaude_transcripteach had their own.replace('/', "-"), and aTempDirpath contains.tmpXXXX— so after the fix they would have planted into a directory the reader no longer reads, failing every ingest test for a reason unrelated to what they test. Both now call one helper that mirrors production, with a comment explaining why it must.2.
--cwdchose the transcripts but never the scopeingest --cwdread another project's sessions while scope still resolved from the process's directory:Importing 33 projects from one terminal filed every one of them under whichever scope that terminal was in — and the response said
scope_origin: "git-root"each time, so the output looked entirely correct while the data was mis-filed.rules::resolve_scope_intakes the directory as an argument;resolve_scopenow delegates to it, so every other caller is unchanged. Explicit--scopestill wins.Verified on real data
The worktree that returned
NOT_FOUNDnow ingests:Gates
fmt·clippy -D warnings· 264 tests · REUSE 3.3 ·makeinfoclean🤖 Generated with Claude Code
https://claude.ai/code/session_016i16R4GhdSffsboRYq97Fs