mirror of
https://github.com/github/spec-kit.git
synced 2026-08-15 14:02:04 +02:00
fix: keep long frontmatter values on a single line (#3989)
`CommandRegistrar.render_frontmatter` calls `yaml.dump()` without `width=`,
so PyYAML applies its default ~80-column wrap and folds any long scalar onto
a continuation line.
A `description` longer than roughly 80 characters is therefore rendered as:
---
name: speckit-implement
description: Execute the implementation plan by processing and executing all tasks
defined in tasks.md
---
The YAML remains valid and round-trips faithfully through `yaml.safe_load`,
so this is not data loss. It is a shape inconsistency with real consequences:
- Hand-written core command templates always keep `description` on one line,
so preset- and extension-rendered commands do not match the files they sit
beside in the same directory.
- Consumers that read frontmatter line-wise rather than with a YAML parser
see the description truncated at the fold, followed by a stray line. Spec
Kit itself hand-builds SKILL.md frontmatter in the skills path (see #3391),
so this is not a hypothetical class of consumer.
- `speckit.implement`'s own description is 89 characters, so a preset that
overrides it hits this immediately.
`width=float("inf")` disables the line-wrapping only; escaping, quoting and
the handling of genuinely multi-line values are unchanged, since PyYAML
selects the scalar style before applying width.
Adds a regression test that fails without the change.
Verified against the repo's own suite: 6354 passed. Four failures in
tests/integrations/test_integration_subcommand.py are present on a clean
checkout too (ANSI escapes in captured output) and are unrelated.
This commit is contained in:
@@ -157,7 +157,11 @@ class CommandRegistrar:
|
||||
return ""
|
||||
|
||||
yaml_str = yaml.dump(
|
||||
fm, default_flow_style=False, sort_keys=False, allow_unicode=True
|
||||
fm,
|
||||
default_flow_style=False,
|
||||
sort_keys=False,
|
||||
allow_unicode=True,
|
||||
width=float("inf"),
|
||||
)
|
||||
return f"---\n{yaml_str}---\n"
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ import platform
|
||||
import tempfile
|
||||
import shutil
|
||||
import tomllib
|
||||
import yaml
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
from datetime import datetime, timezone
|
||||
@@ -2996,6 +2997,30 @@ Real body starts here.
|
||||
assert "Prüfe Konformität" in output
|
||||
assert "\\u" not in output
|
||||
|
||||
def test_render_frontmatter_keeps_long_description_on_one_line(self):
|
||||
"""A long description must not be folded across lines.
|
||||
|
||||
PyYAML wraps plain scalars at ~80 columns by default, which splits a
|
||||
long ``description`` onto a continuation line. The YAML stays valid,
|
||||
but the rendered frontmatter then differs in shape from the
|
||||
hand-written core command templates, where ``description`` is always a
|
||||
single line -- and consumers that read frontmatter line-wise see a
|
||||
truncated description followed by a stray line.
|
||||
"""
|
||||
long_description = (
|
||||
"Execute the implementation plan by processing and executing all "
|
||||
"tasks defined in tasks.md"
|
||||
)
|
||||
frontmatter = {"name": "speckit-implement", "description": long_description}
|
||||
|
||||
registrar = CommandRegistrar()
|
||||
output = registrar.render_frontmatter(frontmatter)
|
||||
|
||||
assert f"description: {long_description}\n" in output
|
||||
|
||||
body = output.split("---\n")[1]
|
||||
assert yaml.safe_load(body)["description"] == long_description
|
||||
|
||||
def test_adjust_script_paths_does_not_mutate_input(self):
|
||||
"""Path adjustments should not mutate caller-owned frontmatter dicts."""
|
||||
from specify_cli.agents import CommandRegistrar as AgentCommandRegistrar
|
||||
|
||||
Reference in New Issue
Block a user