Write or update an entity page in entities/, managing frontmatter. Frontmatter fields: ``sources`` (list), ``type`` (one of the entity enum, capitalized on write), ``description`` (one-liner), and optional ``aliases`` (list, omitted when empty). On update the new source is prepended and
(
wiki_dir: Path,
name: str,
content: str,
source_file: str,
is_update: bool,
brief: str = "",
type_: str = "other",
aliases: list[str] | None = None,
)
| 1022 | |
| 1023 | |
| 1024 | def _write_entity( |
| 1025 | wiki_dir: Path, |
| 1026 | name: str, |
| 1027 | content: str, |
| 1028 | source_file: str, |
| 1029 | is_update: bool, |
| 1030 | brief: str = "", |
| 1031 | type_: str = "other", |
| 1032 | aliases: list[str] | None = None, |
| 1033 | ) -> None: |
| 1034 | """Write or update an entity page in entities/, managing frontmatter. |
| 1035 | |
| 1036 | Frontmatter fields: ``sources`` (list), ``type`` (one of the entity |
| 1037 | enum, capitalized on write), ``description`` (one-liner), and optional |
| 1038 | ``aliases`` (list, omitted when empty). On update the new source is prepended and the body replaced |
| 1039 | with the LLM rewrite; ``type`` is preserved from the new write. |
| 1040 | """ |
| 1041 | entities_dir = wiki_dir / "entities" |
| 1042 | entities_dir.mkdir(parents=True, exist_ok=True) |
| 1043 | safe_name = _sanitize_concept_name(name) |
| 1044 | path = (entities_dir / f"{safe_name}.md").resolve() |
| 1045 | if not path.is_relative_to(entities_dir.resolve()): |
| 1046 | logger.warning("Entity name escapes entities dir: %s", name) |
| 1047 | return |
| 1048 | |
| 1049 | # Strip any frontmatter the LLM body may carry. |
| 1050 | clean_parts = frontmatter.split(content) |
| 1051 | clean = clean_parts[1].lstrip("\n") if clean_parts is not None else content |
| 1052 | |
| 1053 | def _build_entity_frontmatter(sources: list[str]) -> str: |
| 1054 | fm_lines = [_yaml_list_line("sources", sources)] |
| 1055 | fm_lines.append(_yaml_kv_line("type", (type_ or "other").title())) |
| 1056 | if brief: |
| 1057 | fm_lines.append(_yaml_kv_line("description", brief)) |
| 1058 | if aliases: |
| 1059 | fm_lines.append(_yaml_list_line("aliases", aliases)) |
| 1060 | return "---\n" + "\n".join(fm_lines) + "\n---\n\n" |
| 1061 | |
| 1062 | if is_update and path.exists(): |
| 1063 | existing = path.read_text(encoding="utf-8") |
| 1064 | if source_file not in existing: |
| 1065 | existing = _prepend_source_to_frontmatter(existing, source_file) |
| 1066 | ex_parts = frontmatter.split(existing) |
| 1067 | if ex_parts is not None: |
| 1068 | fm_block, _ = ex_parts |
| 1069 | fm_block = _set_fm_line(fm_block, "description", brief) if brief else fm_block |
| 1070 | fm_block = _set_fm_line(fm_block, "type", type_.title()) if type_ else fm_block |
| 1071 | # Drop any legacy ``brief:`` key (migrated to ``description:``), |
| 1072 | # mirroring _write_concept's update path. |
| 1073 | fm_block = frontmatter.drop_line(fm_block, "brief") |
| 1074 | existing = fm_block + "\n" + clean |
| 1075 | else: |
| 1076 | # Malformed/absent frontmatter (opening ``---`` with no closing |
| 1077 | # delimiter, or no frontmatter at all): rebuild valid frontmatter |
| 1078 | # rather than writing a body-only page. Recover any sources already |
| 1079 | # listed in the broken block first — otherwise a multi-source |
| 1080 | # entity would be truncated to just this document. |
| 1081 | recovered: list[str] = [] |