Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions src/docgen/narrate_from_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,19 +238,28 @@ def build_owner_hints_guidance(
return "\n".join(f"- {h}" for h in lines if h.strip())


def _stem_belongs_to_segment(seg_id: str, path: Path) -> bool:
"""``01*.md`` also matches segment ``010``; only the id or an ``id-`` stem belongs."""
stem = path.stem
return stem == seg_id or stem.startswith(f"{seg_id}-")


def _fallback_narration_text(directory: Path, seg_id: str) -> str:
if not directory.is_dir():
return ""
for cand in directory.glob(f"{seg_id}*.md"):
if _stem_belongs_to_segment(seg_id, cand):
return cand.read_text(encoding="utf-8")
return ""


def _existing_narration_text(cfg: "Config", seg_id: str) -> str:
"""Return current ``narration/<stem>.md`` text, or empty if missing."""
seg_name = cfg.resolve_segment_name(seg_id)
path = cfg.narration_dir / f"{seg_name}.md"
if not path.is_file():
# Match wizard asset discovery for NN-*.md fallbacks.
if cfg.narration_dir.is_dir():
for cand in cfg.narration_dir.glob(f"{seg_id}-*.md"):
return cand.read_text(encoding="utf-8")
for cand in cfg.narration_dir.glob(f"{seg_id}*.md"):
return cand.read_text(encoding="utf-8")
return ""
return path.read_text(encoding="utf-8")
if path.is_file():
return path.read_text(encoding="utf-8")
return _fallback_narration_text(cfg.narration_dir, seg_id)


def generate_narration_markdown(
Expand Down
30 changes: 30 additions & 0 deletions tests/test_narrate_from_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from docgen.config import Config, ConfigError
from docgen.narrate_from_source import (
_existing_narration_text,
build_owner_hints_guidance,
collect_source_snippets,
generate_narration_markdown,
Expand Down Expand Up @@ -405,3 +406,32 @@ def test_narration_generate_all_empty_all_raises_even_with_default(tmp_path: Pat
)
assert r.exit_code != 0
assert "segments.all is empty" in (r.output + r.stderr)


def _narration_cfg(tmp_path: Path) -> Config:
raw = {
"segments": {"all": ["01"], "default": ["01"]},
"segment_names": {"01": "01-missing"},
"dirs": {"narration": "narration"},
}
(tmp_path / "docgen.yaml").write_text(yaml.dump(raw), encoding="utf-8")
(tmp_path / "narration").mkdir()
return Config.from_yaml(tmp_path / "docgen.yaml")


def test_narration_fallback_does_not_read_another_segment(tmp_path: Path) -> None:
cfg = _narration_cfg(tmp_path)
(tmp_path / "narration" / "010-other.md").write_text("other segment\n", encoding="utf-8")
assert _existing_narration_text(cfg, "01") == ""


def test_narration_fallback_reads_hyphen_stem(tmp_path: Path) -> None:
cfg = _narration_cfg(tmp_path)
(tmp_path / "narration" / "01-demo.md").write_text("this segment\n", encoding="utf-8")
assert _existing_narration_text(cfg, "01") == "this segment\n"


def test_narration_fallback_reads_bare_segment_id(tmp_path: Path) -> None:
cfg = _narration_cfg(tmp_path)
(tmp_path / "narration" / "01.md").write_text("id file\n", encoding="utf-8")
assert _existing_narration_text(cfg, "01") == "id file\n"
Loading