Skip to content

fix(context): accept USER.md-style names for show/pull/push#59

Merged
eddietejeda merged 2 commits intomainfrom
feat/context-push-strip-md-extension
Apr 24, 2026
Merged

fix(context): accept USER.md-style names for show/pull/push#59
eddietejeda merged 2 commits intomainfrom
feat/context-push-strip-md-extension

Conversation

@eddietejeda
Copy link
Copy Markdown
Contributor

Normalizes the context name argument for show, pull, and push: trim, take the final path segment, then strip a trailing .md (ASCII case-insensitive) so autocomplete paths like USER.md or ./DATAMODEL.md map to API stem USER / DATAMODEL and local ./<STEM>.md.

Bugfix: the first implementation compared the last four bytes to .md, but .md is three bytes, so names like USER.md never matched. Suffix handling now uses ".md".len().

Docs: clap help for the three subcommands and a short note in skills/hotdata/SKILL.md.

context list / --prefix are unchanged (prefix still matches server names as typed).

The .md extension is three bytes, but the normalizer took the last four
characters as the suffix, so USER.md compared R.md to .md and never
stripped. Use MD_SUFFIX.len() for slicing and document optional .md on
show/pull/push in help and the hotdata skill.
@sentry
Copy link
Copy Markdown

sentry Bot commented Apr 24, 2026

Codecov Report

❌ Patch coverage is 75.51020% with 12 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/context.rs 75.51% 12 Missing ⚠️

📢 Thoughts on this report? Let us know!

Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

Blocking Issues

  • src/context.rs lines 62-65: normalize_context_cli_name panics on user input that ends with a multi-byte UTF-8 character whose last bytes straddle the 3-byte .md boundary (e.g. "x𝕌" is 5 bytes → start = 2, which lands inside the 4-byte 𝕌 sequence → Rust panics with "byte index is not a char boundary").

Action Required

Replace the byte-level slice with a safe suffix check:

let lower = basename.to_ascii_lowercase();
if lower.ends_with(".md") {
    return basename[..basename.len() - MD_SUFFIX.len()].to_string();
}
basename.to_string()

lower.ends_with(".md") guarantees the last 3 bytes are the ASCII characters ., m, d. Because ASCII bytes are never UTF-8 continuation bytes, basename.len() - 3 is then guaranteed to be a valid character boundary, making the slice safe.

Comment thread src/context.rs Outdated
Check the last three bytes on the UTF-8 byte slice before slicing the str,
so stems like x𝕌 (without .md) do not use a misaligned str index.

Adds regression tests for multibyte stems with and without .md.
Copy link
Copy Markdown
Contributor

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blocking issue from cycle 1 is fixed. The byte-level suffix check in normalize_context_cli_name is correct: it only slices basename[..i] after confirming the last three bytes are ASCII .md, which guarantees i is a valid UTF-8 char boundary. Tests cover the multi-byte edge cases directly.

@eddietejeda eddietejeda merged commit 73209ea into main Apr 24, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant