What happens
In project moby-dick, the source text is stored as moby-dick.txt (the layout the literary-analysis skill prescribes: <work>.txt in project <work>). The skill's documented read fails:
bm cat moby-dick.txt --lines 6684-6696 --project moby-dick --plain
Error: cat: 'moby-dick.txt' names a project, not a note
The qualified spelling bm cat moby-dick/moby-dick.txt --project moby-dick … works. Any note whose file stem equals its project's name hits this, with or without an extension.
Mechanism
resolve_project_path_route, rule 3b ("the explicit project's own permalink, spelled as the prefix"), calls split_project_permalink_prefix(candidate, (generate_permalink(explicit),)). The splitter compares generate_permalink("/".join(segments[:depth])) with the project permalink, and generate_permalink drops the file extension: generate_permalink("moby-dick.txt") → moby-dick. So the single segment moby-dick.txt is claimed as the project itself with an empty remainder, and cat refuses "names a project, not a note".
The comparison is meant to absorb case and spacing ("My Project" → "my-project"); a project name never carries a file extension, so extension stripping is an over-match here.
Expected
A bare identifier that is a note in the named project resolves to that note. A prefix claim that would leave an empty remainder should require the raw segment to spell the project permalink (no extension dropped), or fall back to note resolution when a note with that identifier exists in the explicit project.
Found during the #1398 Moby Dick qualitative run; the skill will document the qualified form as a workaround meanwhile.
🤖 Generated with Claude Code
https://claude.ai/code/session_014pmKq6bqCi6Zp6BTHuZjrp
What happens
In project
moby-dick, the source text is stored asmoby-dick.txt(the layout the literary-analysis skill prescribes:<work>.txtin project<work>). The skill's documented read fails:The qualified spelling
bm cat moby-dick/moby-dick.txt --project moby-dick …works. Any note whose file stem equals its project's name hits this, with or without an extension.Mechanism
resolve_project_path_route, rule 3b ("the explicit project's own permalink, spelled as the prefix"), callssplit_project_permalink_prefix(candidate, (generate_permalink(explicit),)). The splitter comparesgenerate_permalink("/".join(segments[:depth]))with the project permalink, andgenerate_permalinkdrops the file extension:generate_permalink("moby-dick.txt")→moby-dick. So the single segmentmoby-dick.txtis claimed as the project itself with an empty remainder, andcatrefuses "names a project, not a note".The comparison is meant to absorb case and spacing ("My Project" → "my-project"); a project name never carries a file extension, so extension stripping is an over-match here.
Expected
A bare identifier that is a note in the named project resolves to that note. A prefix claim that would leave an empty remainder should require the raw segment to spell the project permalink (no extension dropped), or fall back to note resolution when a note with that identifier exists in the explicit project.
Found during the #1398 Moby Dick qualitative run; the skill will document the qualified form as a workaround meanwhile.
🤖 Generated with Claude Code
https://claude.ai/code/session_014pmKq6bqCi6Zp6BTHuZjrp