Skip to content

fix(integrations): stop frontmatter injection gluing onto a missing trailing newline - #4570

Open
Noor-ul-ain001 wants to merge 1 commit into
github:mainfrom
Noor-ul-ain001:fix/frontmatter-flag-no-trailing-newline
Open

fix(integrations): stop frontmatter injection gluing onto a missing trailing newline#4570
Noor-ul-ain001 wants to merge 1 commit into
github:mainfrom
Noor-ul-ain001:fix/frontmatter-flag-no-trailing-newline

Conversation

@Noor-ul-ain001

Copy link
Copy Markdown
Contributor

Summary

_inject_frontmatter_flag() in ClaudeIntegration/VibeIntegration/AlquimiaAIIntegration detects 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, producing user-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, then disable-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.

>>> ClaudeIntegration._inject_frontmatter_flag("---\nname: x\n---", "user-invocable")
'---\nname: x\nuser-invocable: true---'          # corrupted delimiter
>>> # a second call on that output:
>>> ClaudeIntegration._inject_frontmatter_flag(_, "disable-model-invocation", "false")
'---\nname: x\nuser-invocable: true---'           # unchanged -- silently dropped

DroidIntegration's own copy of this exact helper already emits an unconditional \n instead 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_flag now always emits f"{key}: {value}\n", matching DroidIntegration.
  • Added a regression test to each affected integration's test file, covering both the single-call corruption and the chained-calls silent-drop.

Test plan

  • ruff check . clean
  • New tests fail against the pre-fix code (verified via test-the-test) and pass with the fix
  • Full tests/integrations/test_integration_{claude,vibe,alquimia,droid}.py suite: 185 passed, 1 pre-existing/unrelated skip

…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
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