fix(integrations): stop frontmatter injection gluing onto a missing trailing newline - #4570
Open
Noor-ul-ain001 wants to merge 1 commit into
Open
Conversation
…railing newline ClaudeIntegration/VibeIntegration/AlquimiaAIIntegration's _inject_frontmatter_flag() detected the closing "---" line's existing EOL and reused it when injecting a new key -- so when that "---" was the file's last line with no trailing newline, the injected text was appended with no newline at all, producing "user-invocable: true---" instead of a properly separated line. This corrupts the frontmatter (the closing delimiter is no longer alone on its own line) and, since post_process_skill_content() chains multiple injection calls, silently drops every subsequent key: a second call's pre-scan can no longer find a second "---" line to inject before, so e.g. "disable-model-invocation: false" is never added at all. post_process_skill_content() runs on content from "external skill generators (presets, extensions)" per its own docstring, so a trailing newline after the closing delimiter isn't guaranteed. DroidIntegration's own copy of this helper already emits an unconditional "\n" instead of detecting/reusing the existing EOL, exactly avoiding this bug -- ported that fix to the other three implementations. Added a regression test to each of the three affected integrations' test files, covering both the single-call corruption and the chained-calls silent-drop. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01U74yBbvVQCPwB7Ed8Dzeu6
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
_inject_frontmatter_flag()inClaudeIntegration/VibeIntegration/AlquimiaAIIntegrationdetects the closing---line's existing EOL and reuses it when injecting a new frontmatter key. When that---is the file's last line with no trailing newline, the injected text is appended with no newline separator at all, producinguser-invocable: true---instead of a clean, separately-lined---.This corrupts the frontmatter (the closing delimiter is no longer alone on its own line), and since
post_process_skill_content()chains multiple calls (user-invocable, thendisable-model-invocation, then any fork-context keys), the second call's pre-scan can no longer find a second---line at all — so every subsequent key injection is silently dropped, not just corrupted.post_process_skill_content()runs on content from "external skill generators (presets, extensions)" per its own docstring, so a trailing newline after the closing delimiter isn't guaranteed.DroidIntegration's own copy of this exact helper already emits an unconditional\ninstead of detecting/reusing the existing EOL, avoiding this bug entirely. Ported that fix to the other three implementations that share the same code.Changes
src/specify_cli/integrations/claude/__init__.py,vibe/__init__.py,alquimia/__init__.py:_inject_frontmatter_flagnow always emitsf"{key}: {value}\n", matchingDroidIntegration.Test plan
ruff check .cleantests/integrations/test_integration_{claude,vibe,alquimia,droid}.pysuite: 185 passed, 1 pre-existing/unrelated skip