@@ -471,6 +471,101 @@ def test_inject_argument_hint_skips_if_already_present(self):
471471 hint_count = sum (1 for ln in lines if ln .startswith ("argument-hint:" ))
472472 assert hint_count == 1
473473
474+ def test_inject_argument_hint_survives_folded_description (self ):
475+ """A long description folded across lines must not corrupt the YAML (#4044).
476+
477+ A description long enough for the YAML dumper to fold it into a
478+ multi-line plain scalar previously had ``argument-hint:`` spliced
479+ into the *middle* of that scalar, producing invalid YAML.
480+ """
481+ from specify_cli .integrations .alquimia import AlquimiaAIIntegration
482+
483+ frontmatter = {
484+ "name" : "speckit-specify" ,
485+ "description" : (
486+ "Create or update the feature specification from a natural "
487+ "language feature description. Also accepts an issue URL "
488+ "resolved via gh CLI (demo customization)."
489+ ),
490+ "compatibility" : "Requires spec-kit project structure with .specify/ directory" ,
491+ }
492+ frontmatter_text = yaml .safe_dump (
493+ frontmatter , sort_keys = False , allow_unicode = True
494+ ).strip ()
495+ content = f"---\n { frontmatter_text } \n ---\n \n Body text\n "
496+ assert "\n " in content , "fixture description must actually fold across lines"
497+
498+ result = AlquimiaAIIntegration .inject_argument_hint (
499+ content , "Describe the feature"
500+ )
501+
502+ parsed = yaml .safe_load (result .split ("---" )[1 ])
503+ assert parsed ["argument-hint" ] == "Describe the feature"
504+ assert parsed ["description" ] == frontmatter ["description" ]
505+
506+ def test_inject_argument_hint_survives_quoted_folded_description (self ):
507+ """A folded description forced into quotes must not absorb the hint (#4044)."""
508+ from specify_cli .integrations .alquimia import AlquimiaAIIntegration
509+
510+ frontmatter = {
511+ "name" : "speckit-specify" ,
512+ "description" : (
513+ "Create or update the feature specification from a natural "
514+ "language feature description. Also accepts a GitHub "
515+ "issue/PR URL or #N reference resolved via gh CLI (demo)."
516+ ),
517+ "compatibility" : "Requires spec-kit project structure with .specify/ directory" ,
518+ }
519+ frontmatter_text = yaml .safe_dump (
520+ frontmatter , sort_keys = False , allow_unicode = True
521+ ).strip ()
522+ content = f"---\n { frontmatter_text } \n ---\n \n Body text\n "
523+ assert "\n " in content , "fixture description must actually fold across lines"
524+
525+ result = AlquimiaAIIntegration .inject_argument_hint (
526+ content , "Describe the feature"
527+ )
528+
529+ parsed = yaml .safe_load (result .split ("---" )[1 ])
530+ assert parsed ["argument-hint" ] == "Describe the feature"
531+ assert parsed ["description" ] == frontmatter ["description" ]
532+
533+ def test_inject_argument_hint_survives_multi_paragraph_description (self ):
534+ """A description with an embedded blank line must not absorb the hint.
535+
536+ PyYAML serializes an embedded ``\\ n\\ n`` inside a quoted scalar as
537+ unindented blank lines, not indented ones, so a fix that only skips
538+ indented continuation lines still fails on this case.
539+ """
540+ from specify_cli .integrations .alquimia import AlquimiaAIIntegration
541+
542+ frontmatter = {
543+ "name" : "speckit-specify" ,
544+ "description" : (
545+ "First paragraph of a fairly long description that will "
546+ "need to wrap across multiple lines when dumped by PyYAML."
547+ "\n \n "
548+ "Second paragraph continues the description after a blank "
549+ "line separator to force embedded newlines in the scalar."
550+ ),
551+ "compatibility" : "Requires spec-kit project structure with .specify/ directory" ,
552+ }
553+ frontmatter_text = yaml .safe_dump (
554+ frontmatter , sort_keys = False , allow_unicode = True
555+ ).strip ()
556+ content = f"---\n { frontmatter_text } \n ---\n \n Body text\n "
557+ assert "\n \n " in frontmatter_text , (
558+ "fixture must produce a blank continuation line"
559+ )
560+
561+ result = AlquimiaAIIntegration .inject_argument_hint (
562+ content , "Describe the feature"
563+ )
564+
565+ parsed = yaml .safe_load (result .split ("---" )[1 ])
566+ assert parsed ["argument-hint" ] == "Describe the feature"
567+ assert parsed ["description" ] == frontmatter ["description" ]
568+
474569
475570class TestAlquimiaDisableModelInvocation :
476571 """Verify disable-model-invocation is false for Alquimia skills."""
0 commit comments