Compare commits

...

1 Commits

Author SHA1 Message Date
torben f63a72cb24 fix: raw_dir-Fixture kappt config.ROOT, private Fixture-Namen ersetzt (2.1.1)
CI / verify (push) Successful in 42s
Release / release (push) Successful in 37s
Files changed:
- CHANGES.md
- VERSION
- tools/chemenu/tests/conftest.py
- tools/chemenu/tests/test_corpus_diff.py
- tools/chemenu/tests/test_index_build.py
- tools/chemenu/tests/test_kb_collections.py
- tools/chemenu/tests/test_lint.py
- tools/chemenu/tests/test_migrate_cmd.py
- tools/chemenu/tests/test_new_page.py
- tools/chemenu/tests/test_page_ops.py
- tools/chemenu/tests/test_provenance.py
- tools/chemenu/tests/test_search.py
- tools/chemenu/tests/test_touch.py
2026-09-01 17:03:51 +02:00
13 changed files with 138 additions and 84 deletions
+37
View File
@@ -20,6 +20,43 @@ their date-only headings.
---
## 2.1.1 - 2026-09-01 - raw_dir-Fixture kappt config.ROOT; letzte private Fixture-Namen ersetzt
**Author:** Torben Nehmer
Der erste CI-Lauf nach der Korpus-Bereinigung wurde rot, während dieselbe Suite lokal grün
blieb: `test_legacy_source_pages_flags_url_and_directory` scheiterte mit
`KeyError: 'Source - DirBacked'`.
**Die Ursache ist keine Testschwäche, sondern eine Umgebungsabhängigkeit.** Der Test legt eine
Quellenseite mit `source: raw/documents` an und erwartet, dass `legacy_source_pages()` sie als
„directory, not a file" meldet. Die Prüfung dort ist `(config.ROOT / legacy).is_dir()` — sie
löst also gegen das *echte* Repo-Wurzelverzeichnis auf, während die `raw_dir`-Fixture ihren
Baum unter `tmp_path` baut. Der Test war nie hermetisch; er bestand, weil dieser Checkout
zufällig ein `raw/documents/` besaß.
Die Korpus-Bereinigung hat dieses Verzeichnis geleert. Git verfolgt keine leeren Verzeichnisse,
also verschwand es im CI-Checkout und blieb im lokalen Arbeitsbaum stehen — grün hier, rot
dort, ohne dass sich am Test etwas geändert hätte.
**Geschlossen in der Fixture, nicht im Test.** `raw_dir` setzt jetzt `config.ROOT` auf
`tmp_path`. Das ist dieselbe Bauart und dasselbe Argument wie bei `hermetic_environment`
(Gitea #8): Wenn eine Umgebungsabhängigkeit lokal unsichtbar ist, gehört sie an der Stelle
geschlossen, die alle Tests erreicht, statt bei dem einen, der zufällig darüber stolpert.
Nachgewiesen, indem `raw/documents/` lokal entfernt und die Suite erneut gefahren wurde — 38
Provenance-Tests grün ohne das Verzeichnis, vorher rot.
**Fixture-Namen.** Die Suite benutzte weiterhin reale Systemnamen der Ursprungsinstanz als
Fixture-Bezeichner (`atlantis`, `abydos`, `Nathan`, `hermes`, `ecodms`, `Opa Hasso`). In einem
öffentlichen Repo beschreiben sie nichts, verraten aber die Namensgebung einer privaten
Umgebung. Ersetzt durch `aurora`, `almanac`, `Borealis`, `gateway`, `docstore`. `gdeploy`
bleibt: die Seite existiert im öffentlichen Korpus.
**Dateien:** `tools/chemenu/tests/conftest.py` (`raw_dir`), sämtliche Testdateien mit
Fixture-Namen.
---
## 2.1.0 - 2026-09-01 - Dual-Lizenz AGPL-3.0/CC-BY-4.0, und ein Leak-Canary fuer dist export
**Author:** Torben Nehmer
+1 -1
View File
@@ -1 +1 @@
2.1.0
2.1.1
+24 -7
View File
@@ -3,6 +3,7 @@ from pathlib import Path
import pytest
from chemenu import config
from chemenu.frontmatter_io import write_page
# Environment the tool reads for its own behaviour. Cleared for every test, so
@@ -92,10 +93,26 @@ def isolated_trace_dir(
@pytest.fixture
def raw_dir(tmp_path: Path) -> Path:
def raw_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Path:
"""A small fake raw/ tree sitting next to the kb_dir fixture (same
tmp_path), for provenance-coverage tests. One file is deliberately left
uncovered by any source page."""
uncovered by any source page.
`config.ROOT` is repointed at `tmp_path` for the same reason
`hermetic_environment` clears the environment: a `raw/...` path in a
fixture page is resolved against the *repository* root by the code under
test (`provenance.legacy_source_pages`, for one), so without this the
fixture builds a raw tree that the code never looks at and answers from
the developer's own `raw/` instead.
That was not theoretical. `test_legacy_source_pages_flags_url_and_directory`
passed for months only because this checkout happened to have a
`raw/documents/` directory; the run that emptied it turned the test red in
CI while it stayed green locally, because git does not track empty
directories and the local one survived. Same shape as Gitea #8, closed the
same way - in the fixture, not in the one test that happened to trip.
"""
monkeypatch.setattr(config, "ROOT", tmp_path)
raw = tmp_path / "raw"
(raw / "notes").mkdir(parents=True)
(raw / "notes" / "Aurora.md").write_text("# Aurora raw notes\n", encoding="utf-8")
@@ -126,19 +143,19 @@ def kb_dir(tmp_path: Path) -> Path:
{
"type": "types/entity.md", "entity_type": "system",
"tags": ["server"], "created": "2026-07-31", "modified": "2026-07-31",
"related": ["Nathan"], "sources": [], "confidence": 0.9,
"related": ["Borealis"], "sources": [], "confidence": 0.9,
"summary": "Server hosting DocStore with ZFS storage",
},
"\n# aurora\n\n## Description\n\nHosts things.\n\n## Relationships\n\n- **Related to:** [[Nathan]]\n\n## See Also\n\n- [[Nathan]]\n",
"\n# aurora\n\n## Description\n\nHosts things.\n\n## Relationships\n\n- **Related to:** [[Borealis]]\n\n## See Also\n\n- [[Borealis]]\n",
)
write_page(
kb / "entities/systems/Nathan.md",
kb / "entities/systems/Borealis.md",
{
"type": "types/entity.md", "entity_type": "system",
"tags": ["workstation"], "created": "2026-08-02", "modified": "2026-08-02",
"related": ["aurora"], "sources": [], "confidence": 0.9,
},
"\n# Nathan\n\n## Description\n\nA workstation.\n\n## Relationships\n\n- **Related to:** [[aurora]]\n",
"\n# Borealis\n\n## Description\n\nA workstation.\n\n## Relationships\n\n- **Related to:** [[aurora]]\n",
)
write_page(
kb / "entities/tools/gdeploy.md",
@@ -169,7 +186,7 @@ def kb_dir(tmp_path: Path) -> Path:
)
(kb / "index.md").write_text(
"# Wiki Index\n\n[[aurora]] [[Nathan]] [[gdeploy]] [[Modbus]] [[Source - Aurora]]\n",
"# Wiki Index\n\n[[aurora]] [[Borealis]] [[gdeploy]] [[Modbus]] [[Source - Aurora]]\n",
encoding="utf-8",
)
(kb / "log.md").write_text("# Wiki Log\n", encoding="utf-8")
+6 -6
View File
@@ -15,8 +15,8 @@ from chemenu.page import Page
BODY = """
# Aurora
Runs [[DocStore]] and talks to [[Nathan]].[^src-notes]
The second mention of [[Nathan]] is what a careless rewrite loses.
Runs [[DocStore]] and talks to [[Borealis]].[^src-notes]
The second mention of [[Borealis]] is what a careless rewrite loses.
## Fußnoten
@@ -31,7 +31,7 @@ def page(body: str, **frontmatter) -> Page:
"created": "2026-07-31",
"provenance": "sourced",
"confidence_base": 0.9,
"related": ["Nathan"],
"related": ["Borealis"],
"sources": ["Source - Aurora"],
}
base.update(frontmatter)
@@ -57,7 +57,7 @@ def kinds(diff) -> list[str]:
def test_a_dropped_occurrence_is_caught_even_though_the_link_set_is_unchanged():
after = BODY.replace("The second mention of [[Nathan]] is", "Das zweite Vorkommen ist")
after = BODY.replace("The second mention of [[Borealis]] is", "Das zweite Vorkommen ist")
before_shapes, after_shapes = shapes(BODY, after)
# Precondition: the sets really are identical, so a set-based check passes.
@@ -67,7 +67,7 @@ def test_a_dropped_occurrence_is_caught_even_though_the_link_set_is_unchanged():
diff = corpus_diff.compare(before_shapes, after_shapes)
assert kinds(diff) == ["wikilinks"]
assert "'Nathan' 2->1" in diff.findings[0].detail
assert "'Borealis' 2->1" in diff.findings[0].detail
assert not diff.ok
@@ -85,7 +85,7 @@ def test_pure_prose_change_is_not_reported():
def test_a_dropped_citation_is_caught():
after = BODY.replace("[[Nathan]].[^src-notes]", "[[Nathan]].")
after = BODY.replace("[[Borealis]].[^src-notes]", "[[Borealis]].")
diff = corpus_diff.compare(*shapes(BODY, after))
assert "cite-refs" in kinds(diff)
+2 -2
View File
@@ -99,13 +99,13 @@ def test_map_deep_links_an_inlined_area_by_anchor(kb_dir):
def test_collection_shard_holds_the_page_rows(plan, kb_dir):
entities = _shard(plan, kb_dir, "entities")
assert "[[aurora]]" in entities
assert "[[Nathan]]" in entities
assert "[[Borealis]]" in entities
assert "[[gdeploy]]" in entities
def test_pages_are_grouped_by_area_and_sorted_case_insensitively(plan, kb_dir):
systems = _section(_shard(plan, kb_dir, "entities"), f"## {_area_title('system')}")
assert systems.index("[[aurora]]") < systems.index("[[Nathan]]")
assert systems.index("[[aurora]]") < systems.index("[[Borealis]]")
assert "[[gdeploy]]" not in systems
+1 -1
View File
@@ -31,7 +31,7 @@ def test_directory_without_a_contract_is_not_a_collection(repo):
def test_area_resolves_to_its_enclosing_collection(repo):
page = repo / "kb" / "entities" / "systems" / "hermes.md"
page = repo / "kb" / "entities" / "systems" / "gateway.md"
assert kb_collections.kb_collection_of(page) == repo / "kb" / "entities"
+2 -2
View File
@@ -128,9 +128,9 @@ def test_lint_detects_orphan_page(kb_dir):
)
report = run_lint(kb_dir)
assert "isolated" in report["orphan_pages"]
# aurora and Nathan link to each other, so they must not be reported as orphans.
# aurora and Borealis link to each other, so they must not be reported as orphans.
assert "aurora" not in report["orphan_pages"]
assert "Nathan" not in report["orphan_pages"]
assert "Borealis" not in report["orphan_pages"]
def test_lint_detects_missing_frontmatter_fields(kb_dir):
+4 -4
View File
@@ -176,7 +176,7 @@ provenance: sourced
# Aurora
Links to [[Nathan]] and again to [[Nathan]].
Links to [[Borealis]] and again to [[Borealis]].
"""
@@ -214,19 +214,19 @@ def test_verify_is_clean_when_only_prose_moved(git_instance, capsys):
def test_verify_catches_a_dropped_link_against_history(git_instance, capsys):
page = git_instance / "kb" / "entities" / "Aurora.md"
page.write_text(PAGE.replace(" and again to [[Nathan]]", ""), encoding="utf-8")
page.write_text(PAGE.replace(" and again to [[Borealis]]", ""), encoding="utf-8")
with pytest.raises(typer.Exit):
migrate_cmd.verify_command(
from_rev="HEAD", path=None, expect_body_change=False, json_out=True, fail_on_error=True
)
result = json.loads(capsys.readouterr().out)
assert result["findings"][0]["kind"] == "wikilinks"
assert "'Nathan' 2->1" in result["findings"][0]["detail"]
assert "'Borealis' 2->1" in result["findings"][0]["detail"]
def test_verify_scopes_to_a_subtree(git_instance, capsys):
page = git_instance / "kb" / "entities" / "Aurora.md"
page.write_text(PAGE.replace(" and again to [[Nathan]]", ""), encoding="utf-8")
page.write_text(PAGE.replace(" and again to [[Borealis]]", ""), encoding="utf-8")
migrate_cmd.verify_command(
from_rev="HEAD",
path=["kb/concepts"],
+8 -8
View File
@@ -60,7 +60,7 @@ def test_new_entity_creates_page_with_expected_frontmatter(monkeypatch, kb_dir):
result = _invoke_new(monkeypatch, kb_dir, [
"new", "entity", "--name", "gateway.example.net",
"--set", "entity_type=system", "--set", "tags=gateway,firewall",
"--set", "related=Nathan", "--set", "confidence=0.9",
"--set", "related=Borealis", "--set", "confidence=0.9",
"--set", "provenance=general",
])
assert result.exit_code == 0, result.output
@@ -70,7 +70,7 @@ def test_new_entity_creates_page_with_expected_frontmatter(monkeypatch, kb_dir):
assert fm["type"] == "types/entity.md"
assert fm["entity_type"] == "system"
assert fm["tags"] == ["gateway", "firewall"]
assert fm["related"] == ["Nathan"]
assert fm["related"] == ["Borealis"]
assert fm["confidence"] == 0.9
assert "# gateway.example.net" in body
@@ -172,18 +172,18 @@ def test_new_source_prefixes_title_and_prefills_related_entities(monkeypatch, kb
result = _invoke_new(monkeypatch, kb_dir, [
"new", "source", "--name", "gateway.example.net",
"--set", "raw_files=raw/notes/gateway.example.net.md",
"--set", "entities=aurora,Nathan",
"--set", "entities=aurora,Borealis",
])
assert result.exit_code == 0, result.output
path = kb_dir / "sources/Source - gateway.example.net.md"
assert path.exists()
fm, body = read_page(path)
assert fm["type"] == "types/source.md"
assert fm["entities"] == ["aurora", "Nathan"]
assert fm["entities"] == ["aurora", "Borealis"]
assert fm["author"] == "Torben" # WIKI_AUTHOR override
assert fm["source_type"] == "notes" # schema default
assert "[[aurora]]" in body
assert "[[Nathan]]" in body
assert "[[Borealis]]" in body
def test_new_source_author_falls_back_to_git_config(monkeypatch, kb_dir):
@@ -264,13 +264,13 @@ def test_new_concept_rejects_invalid_provenance(monkeypatch, kb_dir):
def test_new_comparison_renders_table_columns(monkeypatch, kb_dir):
result = _invoke_new(monkeypatch, kb_dir, [
"new", "comparison", "--name", "A vs B", "--set", "entities=aurora,Nathan",
"new", "comparison", "--name", "A vs B", "--set", "entities=aurora,Borealis",
])
assert result.exit_code == 0, result.output
fm, body = read_page(kb_dir / "comparisons/A vs B.md")
assert fm["entities"] == ["aurora", "Nathan"]
assert fm["entities"] == ["aurora", "Borealis"]
# Table columns are rendered by the generic table_* template filters.
assert "[[aurora]] | [[Nathan]]" in body
assert "[[aurora]] | [[Borealis]]" in body
def test_new_comparison_rejects_single_entity(monkeypatch, kb_dir):
+45 -45
View File
@@ -78,49 +78,49 @@ def test_retarget_cite_ids_is_noop_without_a_footnotes_block():
def test_rename_refreshes_stale_slug_derived_cite_id(patched_wiki):
old_id = cite_id("Nathan")
old_id = cite_id("Borealis")
write_page(
patched_wiki / "concepts/uses-nathan.md",
patched_wiki / "concepts/uses-borealis.md",
{
"type": "types/concept.md", "concept_type": "protocol",
"tags": [], "created": "2026-07-25", "modified": "2026-07-25",
"related": [], "sources": [], "confidence": 0.7,
},
f"\n# uses-nathan\n\nRuns on it [^{old_id}].\n\n## Footnotes\n\n[^{old_id}]: [[Nathan]]\n",
f"\n# uses-borealis\n\nRuns on it [^{old_id}].\n\n## Footnotes\n\n[^{old_id}]: [[Borealis]]\n",
)
page_ops.rename_command(old="Nathan", new="nathan-ws", dry_run=False)
page_ops.rename_command(old="Borealis", new="borealis-ws", dry_run=False)
_frontmatter, body = read_page(patched_wiki / "concepts/uses-nathan.md")
new_id = cite_id("nathan-ws")
assert f"[^{new_id}]: [[nathan-ws]]" in body
_frontmatter, body = read_page(patched_wiki / "concepts/uses-borealis.md")
new_id = cite_id("borealis-ws")
assert f"[^{new_id}]: [[borealis-ws]]" in body
assert f"[^{old_id}]" not in body
def test_rename_updates_body_links_and_frontmatter(patched_wiki):
page_ops.rename_command(old="Nathan", new="nathan-ws", dry_run=False)
page_ops.rename_command(old="Borealis", new="borealis-ws", dry_run=False)
assert (patched_wiki / "entities/systems/nathan-ws.md").exists()
assert not (patched_wiki / "entities/systems/Nathan.md").exists()
assert (patched_wiki / "entities/systems/borealis-ws.md").exists()
assert not (patched_wiki / "entities/systems/Borealis.md").exists()
frontmatter, body = read_page(patched_wiki / "entities/systems/aurora.md")
assert frontmatter["related"] == ["nathan-ws"]
assert "[[nathan-ws]]" in body
assert "[[Nathan]]" not in body
assert frontmatter["related"] == ["borealis-ws"]
assert "[[borealis-ws]]" in body
assert "[[Borealis]]" not in body
def test_rename_rewrites_the_pages_own_h1(patched_wiki):
page_ops.rename_command(old="Nathan", new="nathan-ws", dry_run=False)
_frontmatter, body = read_page(patched_wiki / "entities/systems/nathan-ws.md")
assert "# nathan-ws" in body
assert "# Nathan\n" not in body
page_ops.rename_command(old="Borealis", new="borealis-ws", dry_run=False)
_frontmatter, body = read_page(patched_wiki / "entities/systems/borealis-ws.md")
assert "# borealis-ws" in body
assert "# Borealis\n" not in body
def test_rename_dry_run_writes_nothing(patched_wiki):
page_ops.rename_command(old="Nathan", new="nathan-ws", dry_run=True)
assert (patched_wiki / "entities/systems/Nathan.md").exists()
page_ops.rename_command(old="Borealis", new="borealis-ws", dry_run=True)
assert (patched_wiki / "entities/systems/Borealis.md").exists()
frontmatter, _body = read_page(patched_wiki / "entities/systems/aurora.md")
assert frontmatter["related"] == ["Nathan"]
assert frontmatter["related"] == ["Borealis"]
def test_rename_rejects_missing_page(patched_wiki):
@@ -136,15 +136,15 @@ def test_rename_repoints_references_to_an_existing_page(patched_wiki):
patched_wiki / "entities/tools/gdeploy.md",
{"type": "types/entity.md", "entity_type": "tool", "tags": [],
"created": "2026-07-25", "modified": "2026-07-25",
"related": ["nathan"], "sources": [], "confidence": 0.8},
"\n# gdeploy\n\n## See Also\n\n- [[nathan]]\n",
"related": ["borealis"], "sources": [], "confidence": 0.8},
"\n# gdeploy\n\n## See Also\n\n- [[borealis]]\n",
)
page_ops.rename_command(old="nathan", new="Nathan", dry_run=False)
page_ops.rename_command(old="borealis", new="Borealis", dry_run=False)
frontmatter, body = read_page(patched_wiki / "entities/tools/gdeploy.md")
assert frontmatter["related"] == ["Nathan"]
assert "[[Nathan]]" in body
assert (patched_wiki / "entities/systems/Nathan.md").exists()
assert frontmatter["related"] == ["Borealis"]
assert "[[Borealis]]" in body
assert (patched_wiki / "entities/systems/Borealis.md").exists()
def test_rename_reference_only_mode_requires_the_target_to_exist(patched_wiki):
@@ -161,12 +161,12 @@ def test_rename_reference_only_mode_requires_the_target_to_exist(patched_wiki):
def test_rename_rejects_existing_target(patched_wiki):
with pytest.raises(typer.Exit):
page_ops.rename_command(old="Nathan", new="aurora", dry_run=False)
page_ops.rename_command(old="Borealis", new="aurora", dry_run=False)
def test_rename_rejects_identical_titles(patched_wiki):
with pytest.raises(typer.Exit):
page_ops.rename_command(old="Nathan", new="Nathan", dry_run=False)
page_ops.rename_command(old="Borealis", new="Borealis", dry_run=False)
def test_rename_fixes_a_dangling_source_reference(patched_wiki):
@@ -201,24 +201,24 @@ def test_rename_stops_before_renaming_the_file_if_a_reference_write_fails(patche
monkeypatch.setattr(page_ops_module, "write_page", flaky_write_page)
with pytest.raises(typer.Exit):
page_ops.rename_command(old="Nathan", new="nathan-ws", dry_run=False)
page_ops.rename_command(old="Borealis", new="borealis-ws", dry_run=False)
assert (patched_wiki / "entities/systems/Nathan.md").exists()
assert not (patched_wiki / "entities/systems/nathan-ws.md").exists()
assert (patched_wiki / "entities/systems/Borealis.md").exists()
assert not (patched_wiki / "entities/systems/borealis-ws.md").exists()
def test_rm_refuses_referenced_page_without_yes(patched_wiki):
with pytest.raises(typer.Exit):
page_ops.rm_command(page_title="Nathan", yes=False, dry_run=False)
assert (patched_wiki / "entities/systems/Nathan.md").exists()
page_ops.rm_command(page_title="Borealis", yes=False, dry_run=False)
assert (patched_wiki / "entities/systems/Borealis.md").exists()
def test_rm_deletes_and_delinks_with_yes(patched_wiki):
page_ops.rm_command(page_title="Nathan", yes=True, dry_run=False)
page_ops.rm_command(page_title="Borealis", yes=True, dry_run=False)
assert not (patched_wiki / "entities/systems/Nathan.md").exists()
assert not (patched_wiki / "entities/systems/Borealis.md").exists()
frontmatter, body = read_page(patched_wiki / "entities/systems/aurora.md")
assert frontmatter["related"] == []
assert "[[Nathan]]" not in body
assert "[[Borealis]]" not in body
def test_rm_stops_before_deleting_the_file_if_a_delink_write_fails(patched_wiki, monkeypatch):
@@ -234,9 +234,9 @@ def test_rm_stops_before_deleting_the_file_if_a_delink_write_fails(patched_wiki,
monkeypatch.setattr(page_ops_module, "write_page", flaky_write_page)
with pytest.raises(typer.Exit):
page_ops.rm_command(page_title="Nathan", yes=True, dry_run=False)
page_ops.rm_command(page_title="Borealis", yes=True, dry_run=False)
assert (patched_wiki / "entities/systems/Nathan.md").exists()
assert (patched_wiki / "entities/systems/Borealis.md").exists()
def test_rm_of_unreferenced_page_needs_no_confirmation(patched_wiki):
@@ -259,20 +259,20 @@ def test_rm_leaves_prose_references_and_reports_them(patched_wiki, capsys):
{"type": "types/entity.md", "entity_type": "tool", "tags": [],
"created": "2026-07-25", "modified": "2026-07-25", "related": [],
"sources": [], "confidence": 0.8},
"\n# gdeploy\n\n## Description\n\nRuns on [[Nathan]] nightly.\n",
"\n# gdeploy\n\n## Description\n\nRuns on [[Borealis]] nightly.\n",
)
page_ops.rm_command(page_title="Nathan", yes=True, dry_run=False)
page_ops.rm_command(page_title="Borealis", yes=True, dry_run=False)
_frontmatter, body = read_page(patched_wiki / "entities/tools/gdeploy.md")
assert "Runs on [[Nathan]] nightly." in body
assert "remaining [[Nathan]] reference(s)" in capsys.readouterr().out
assert "Runs on [[Borealis]] nightly." in body
assert "remaining [[Borealis]] reference(s)" in capsys.readouterr().out
def test_rm_dry_run_writes_nothing(patched_wiki):
page_ops.rm_command(page_title="Nathan", yes=True, dry_run=True)
assert (patched_wiki / "entities/systems/Nathan.md").exists()
page_ops.rm_command(page_title="Borealis", yes=True, dry_run=True)
assert (patched_wiki / "entities/systems/Borealis.md").exists()
frontmatter, _body = read_page(patched_wiki / "entities/systems/aurora.md")
assert frontmatter["related"] == ["Nathan"]
assert frontmatter["related"] == ["Borealis"]
def test_inbound_pages_sees_frontmatter_only_references(patched_wiki):
+4 -4
View File
@@ -161,7 +161,7 @@ def test_the_block_is_re_emitted_last_so_the_layout_self_heals():
body = (
"# Page\n\nProse [^s-aurora].\n\n"
+ render_cite_block(definitions)
+ "\n## Siehe auch\n\n- [[Nathan]]\n"
+ "\n## Siehe auch\n\n- [[Borealis]]\n"
)
rebuilt = render_page_body(*split_cite_block(body))
assert rebuilt.index("## Siehe auch") < rebuilt.index("[^s-aurora]:")
@@ -173,7 +173,7 @@ def test_repeated_round_trips_are_stable():
body = (
"# Page\n\nProse [^s-aurora].\n\n"
+ render_cite_block(definitions)
+ "\n## Siehe auch\n\n- [[Nathan]]\n"
+ "\n## Siehe auch\n\n- [[Borealis]]\n"
)
once = render_page_body(*split_cite_block(body))
twice = render_page_body(*split_cite_block(once))
@@ -200,7 +200,7 @@ def test_a_citation_used_in_a_rescued_section_still_resolves():
"# Page\n\nProse.\n\n"
"## Fußnoten\n\n"
"[^s-aurora]: [[Source - Aurora]]\n\n"
"## Beziehungen\n\n- **belegt durch:** [[Nathan]] [^s-aurora]\n"
"## Beziehungen\n\n- **belegt durch:** [[Borealis]] [^s-aurora]\n"
)
assert extract_inline_cites(body) == {("Source - Aurora", None)}
@@ -368,7 +368,7 @@ def test_sources_trace_by_raw_and_by_page(kb_dir, raw_dir, monkeypatch):
kb_dir / "entities/systems/aurora.md",
{
"type": "entity", "entity_type": "system", "tags": ["server"],
"created": "2026-07-31", "modified": "2026-07-31", "related": ["Nathan"],
"created": "2026-07-31", "modified": "2026-07-31", "related": ["Borealis"],
"sources": ["Source - Aurora"], "confidence": 0.9,
},
"\n# aurora\n\n## Description\n\nHosts things.\n",
+3 -3
View File
@@ -74,7 +74,7 @@ def test_parse_predicate_rejects_malformed(raw):
def test_exact_match_on_frontmatter_field(search):
assert _titles(search(_q("entity_type=system"))) == ["aurora", "Nathan"]
assert _titles(search(_q("entity_type=system"))) == ["aurora", "Borealis"]
def test_membership_on_list_field(search):
@@ -86,13 +86,13 @@ def test_substring_match_is_case_insensitive(search):
def test_numeric_comparison(search):
assert _titles(search(_q("confidence>=0.9"))) == ["aurora", "Nathan"]
assert _titles(search(_q("confidence>=0.9"))) == ["aurora", "Borealis"]
def test_date_comparison_handles_yaml_date_objects(search):
"""PyYAML parses `modified: 2026-08-02` into a date, not a string - the
comparison has to normalise it or it never matches."""
assert _titles(search(_q("modified>=2026-08-01"))) == ["Nathan"]
assert _titles(search(_q("modified>=2026-08-01"))) == ["Borealis"]
def test_exists_and_absent_are_complementary(search, pages):
+1 -1
View File
@@ -172,7 +172,7 @@ def test_page_reference_fields_are_refused_and_name_xref(touch_wiki, capsys):
frontmatter write would leave the other half stale."""
for field in ("related", "sources", "entities", "concepts"):
with pytest.raises(typer.Exit):
_touch(page_title="aurora", set_fields=[f"{field}=Nathan"])
_touch(page_title="aurora", set_fields=[f"{field}=Borealis"])
assert "xref" in capsys.readouterr().out