Repository navigation
Markdown list bullets are lossy through the skill-guidance seed/render round-trip #1974
Description
Summary
Surfaced during review of #1972 (issue #1965). Out of scope there, captured here while the diagnosis is fresh.
#1965 fixed JSON examples being corrupted through the skill-guidance round-trip (unfenced JSON lost all indentation). The same round-trip is also lossy for markdown list bullets, and this one is arguably the bigger prompt-fidelity loss because it affects far more of the guidance text.
The defect
Source (packages/agent/src/skill_pipeline.rs, Research & Search guidance):
- Use 'collection' to narrow search to a namespace/folder (e.g. collection="Architecture").
- Use 'node_types' to filter by type (e.g. node_types=["task"]) — prefer over 'collection' for type-based filtering.
What the model actually receives after seed → render_skill_instructions → flatten_subtree_content:
Use 'collection' to narrow search to a namespace/folder (e.g. collection="Architecture").
Use 'node_types' to filter by type (e.g. node_types=["task"]) — prefer over 'collection' for type-based filtering.
Two losses:
- The
-marker is stripped, so the text no longer reads as a list. - Each bullet becomes its own node, and
flatten_subtree_contentjoins nodes with\n\n— so a tight list renders as loose paragraphs.
Why it happens
prepare_nodes_from_markdown stores a bullet's content without its - marker (bullet-ness is carried by node structure, not the content string). The read path (flatten_subtree_content, packages/core/src/services/node_service/hierarchy.rs:959) re-emits node.content verbatim and joins with a blank line — it has no notion of re-deriving list markers or tight vs. loose spacing.
Contrast with code-block, which round-trips losslessly precisely because its fence markers are preserved inside content.
Scope
This affects every guidance block that uses bullets — Research & Search (parameter guidance, listing/filter examples), Schema Creation (title_template examples), Graph Editing (ambiguity examples), and the TARGET_TYPE_MUST_EXIST rule's examples. It is not specific to any one skill.
Possible directions (not yet decided)
- Have
flatten_subtree_content's consumer re-derive list markers from node type/structure — but that function is generic and used beyond skills, so changing it has blast radius. - Give the skill-render path its own markdown serializer that reconstructs list syntax, rather than reusing the flat content join.
- Or accept the flattening and stop authoring guidance as lists.
Worth measuring before choosing: guidance wording is load-bearing for agent behavior, so any of these changes the model-facing prompt for every skill and should be evaluated, not assumed neutral.
Related
- Skill seed guidance text should use proper markdown (fenced code blocks) for JSON examples #1965 / Fence JSON examples in skill guidance so they seed as code-block nodes (closes #1965) #1972 — fixed the same class of loss for fenced code examples.
- Make the graph the source of truth for the NodeSpace skill, and decide how guidance reaches external agents #1958 — skill guidance / SKILL.md structural sync; this is a natural companion.
Activity
mstomar125 commentedon Sep 12, 2026
Status-confirmation (2026-09-12): the defect is still present and unfixed against current
main.packages/agent/src/skill_pipeline.rs:368-369still authors the exact bulleted guidance quoted in the issue.prepare_nodes_from_markdown(packages/core/src/markdown/mod.rs:530-531) still strips the-marker intocontent_linewithout recording bullet-ness anywhere else.flatten_subtree_content(nowpackages/core/src/services/node_service/hierarchy.rs:1077, moved from the issue's cited :959) still re-emitsnode.contentverbatim with no marker reconstruction.render_skill_instructions(packages/core/src/ops/skill_ops.rs:76), still does.join("\n\n")— the tight-list-becomes-loose-paragraphs behavior described in the issue is confirmed unchanged.Ownership check per this issue's scope note: this is core-owned code (
hierarchy.rs,skill_ops.rs,markdown/mod.rsall underpackages/core) — notpackages/agentorpackages/skillterritory.packages/agent/src/skill_pipeline.rssupplies only the guidance content; the lossy rendering logic lives entirely inpackages/core. So no sign-off gate applies here.That said, the issue is right that this isn't a safe one-liner:
flatten_subtree_contentis generic and used beyond skills (real blast radius), and each of the three listed directions changes model-facing prompt text for every skill — which the issue itself correctly flags as needing measurement, not an assumed-neutral fix. Not forcing that implementation here. Leaving open in Backlog with this confirmation.malibio commentedon Sep 28, 2026
Frontend: 280 files / 5225 tests passed
Restore list markers when rendering a node subtree to the prompt (closes