feat(wiki): port upstream knowledge quality improvements
setup / install-leaves-tree-clean (push) Waiting to run

Selectively port source coverage and redirect lint, ignore-aware provenance, staging and trust checks from upstream 055d720. Preserve local archive metadata and adapt source-date and defuddle skill guidance.

Keep the existing skills directory, file index and MCP interfaces. Record per-module upstream baselines and exclusions without migrating vault data or changing services.

Validation: 625 tests passed; git diff --check passed.
This commit is contained in:
Codex
2026-11-07 21:49:41 +00:00
parent 82890606aa
commit e943bb329e
17 changed files with 437 additions and 29 deletions
+124
View File
@@ -1065,3 +1065,127 @@ def test_lint_vault_warns_on_undated_counts_and_skips_dated_ones(tmp_path: Path)
lines = page.read_text(encoding="utf-8").splitlines()
assert all(lines[claim["line"] - 1].strip() == claim["text"] for claim in claims)
assert report["status"] == "warn"
def _write_ignored_archive(vault: Path) -> None:
"""`_write_archive_and_manifest`, plus a second archive `.okignore` covers."""
_write_archive_and_manifest(vault)
hidden = vault / "_raw" / "_archived" / "private" / "hidden.md"
hidden.parent.mkdir(parents=True, exist_ok=True)
hidden.write_text("# clip\n", encoding="utf-8")
manifest = json.loads((vault / ".manifest.json").read_text(encoding="utf-8"))
manifest["sources"]["_raw/_archived/private/hidden.md"] = {"pages_produced": ["concepts/alpha.md"]}
(vault / ".manifest.json").write_text(json.dumps(manifest), encoding="utf-8")
(vault / ".okignore").write_text("_raw/_archived/private\n", encoding="utf-8")
def test_snapshot_mismatch_does_not_name_an_ignored_archive(tmp_path: Path) -> None:
vault = tmp_path / "vault"
_clean_pair(vault)
_write_ignored_archive(vault)
rows = lint_vault(vault)["findings"]["snapshot_mismatch"]
assert [row["expected"] for row in rows] == [["_raw/_archived/a.md"]]
def test_a_page_citing_an_ignored_archive_is_not_a_mismatch(tmp_path: Path) -> None:
vault = tmp_path / "vault"
_clean_pair(vault, alpha_snapshots="[_raw/_archived/a.md, _raw/_archived/private/hidden.md]")
_write_ignored_archive(vault)
assert lint_vault(vault)["findings"]["snapshot_mismatch"] == []
def test_uncovered_sources_reports_sources_with_no_surviving_page(tmp_path: Path) -> None:
vault = tmp_path / "vault"
_clean_pair(vault)
(vault / ".manifest.json").write_text(
json.dumps(
{
"sources": [
{"path": "docs/kept.md", "pages_produced": ["concepts/alpha.md"]},
{"path": "docs/partly.md", "pages_produced": ["concepts/beta", "concepts/gone.md"]},
{"path": "docs/empty.md", "pages_produced": []},
{"path": "docs/lost.md", "pages_created": ["concepts/gone.md"]},
{"path": "docs/counts-only.md", "pages_created": 3},
]
}
),
encoding="utf-8",
)
report = lint_vault(vault)
assert report["findings"]["uncovered_sources"] == [
{"source": "docs/empty.md", "issue": "no_pages", "missing": []},
{"source": "docs/lost.md", "issue": "pages_missing", "missing": ["concepts/gone.md"]},
]
assert report["status"] == "warn"
def _redirect_stub(vault: Path, relpath: str, target: str, *, title: str | None = None) -> Path:
"""A wiki-dedup merge leftover: same title/stem as the canonical page,
with a `redirects_to:` pointer in its frontmatter."""
path = _page(vault, relpath, title=title)
text = path.read_text(encoding="utf-8")
path.write_text(
text.replace("\n---\n", f'\nredirects_to: "[[{target}]]"\n---\n', 1),
encoding="utf-8",
)
return path
def test_lint_redirect_stub_is_not_a_duplicate(tmp_path: Path) -> None:
vault = tmp_path / "vault"
_page(vault, "concepts/example.md", title="Example")
_redirect_stub(vault, "entities/example.md", "concepts/example", title="Example")
report = lint_vault(vault, require_trust_ledger=False)
assert report["findings"]["duplicate_titles"] == []
assert report["findings"]["duplicate_stems"] == []
assert report["findings"]["redirect_issues"] == []
def test_lint_redirect_stub_with_missing_target_is_reported(tmp_path: Path) -> None:
vault = tmp_path / "vault"
_page(vault, "concepts/example.md", title="Example")
_redirect_stub(vault, "entities/example.md", "concepts/gone", title="Example")
report = lint_vault(vault, require_trust_ledger=False)
assert report["findings"]["redirect_issues"] == [
{"page": "entities/example.md", "target": "concepts/gone", "issue": "missing_target"}
]
# A broken stub still stays out of the duplicate checks.
assert report["findings"]["duplicate_titles"] == []
assert report["findings"]["duplicate_stems"] == []
def test_lint_redirect_chain_is_reported(tmp_path: Path) -> None:
vault = tmp_path / "vault"
_page(vault, "concepts/example.md", title="Example")
_redirect_stub(vault, "entities/example.md", "concepts/example", title="Example")
_redirect_stub(vault, "references/example.md", "entities/example", title="Example")
report = lint_vault(vault, require_trust_ledger=False)
assert report["findings"]["redirect_issues"] == [
{"page": "references/example.md", "target": "entities/example", "issue": "redirect_chain"}
]
def test_lint_two_real_pages_with_same_title_still_duplicate(tmp_path: Path) -> None:
vault = tmp_path / "vault"
_page(vault, "concepts/example.md", title="Example")
_page(vault, "entities/example.md", title="Example")
report = lint_vault(vault, require_trust_ledger=False)
assert report["findings"]["duplicate_titles"] == [
{"title": "example", "pages": ["concepts/example.md", "entities/example.md"]}
]
assert report["findings"]["duplicate_stems"] == [
{"stem": "example", "pages": ["concepts/example.md", "entities/example.md"]}
]
+11
View File
@@ -4,6 +4,7 @@ from pathlib import Path
from obsidian_wiki.provenance import (
archive_wikilink_relpath,
clip_url_index,
expected_snapshots_for_page,
invert_pages,
parse_snapshots_field,
@@ -218,3 +219,13 @@ def test_archive_wikilink_relpath_rejects_parent_traversal(tmp_path: Path) -> No
vault = tmp_path / "vault"
vault.mkdir()
assert archive_wikilink_relpath(vault, "_raw/_archived/../attention") is None
def test_clip_url_index_honors_okignore(tmp_path: Path) -> None:
for rel, url in (("kept", "https://example.test/kept"), ("private/hidden", "https://example.test/hidden")):
clip = tmp_path / "_raw" / "_archived" / f"{rel}.md"
clip.parent.mkdir(parents=True, exist_ok=True)
clip.write_text(f"---\nurl: {url}\n---\n\nclip\n", encoding="utf-8")
(tmp_path / ".okignore").write_text("_raw/_archived/private\n", encoding="utf-8")
assert clip_url_index(tmp_path) == {"https://example.test/kept": ["_raw/_archived/kept.md"]}
+25
View File
@@ -2,6 +2,8 @@
from __future__ import annotations
from pathlib import Path
import pytest
from obsidian_wiki.staging import (
@@ -200,3 +202,26 @@ def test_log_records_one_line_per_batch(vault):
def test_log_is_silent_when_nothing_happened(vault):
log_decisions(vault, [])
assert not (vault / "log.md").exists()
def test_list_staged_honors_okignore(tmp_path):
write(tmp_path, "_staging/concepts/kept.md", "kept\n")
write(tmp_path, "_staging/private/hidden.md", "hidden\n")
# Staged over an ignored live page: listing it would diff against that page.
write(tmp_path, "notes/old/live.md", "secret\n")
write(tmp_path, "_staging/notes/old/live.md", "revised\n")
write(tmp_path, ".okignore", "_staging/private\n/notes/old\n")
assert [Path(entry.live_path).as_posix() for entry in list_staged(tmp_path)] == ["concepts/kept.md"]
def test_list_staged_does_not_follow_a_symlinked_directory(tmp_path):
vault = tmp_path / "vault"
write(vault, "_staging/concepts/kept.md", "kept\n")
write(tmp_path, "outside/secret.md", "secret\n")
try:
(vault / "_staging" / "link").symlink_to(tmp_path / "outside", target_is_directory=True)
except (OSError, NotImplementedError):
pytest.skip("symlinks unavailable on this platform")
assert [Path(entry.live_path).as_posix() for entry in list_staged(vault)] == ["concepts/kept.md"]
+48
View File
@@ -86,6 +86,7 @@ def test_reviewed_ledger_is_authoritative_instead_of_reclassifying_sources(tmp_p
"score_mismatches": 0,
"missing_pages": 0,
"errors": 0,
"ignored_entries": 0,
}
assert {item["page"] for item in report["reviewed"]} == {
"concepts/alpha.md",
@@ -881,3 +882,50 @@ def test_required_trust_ledger_fails_closed_when_missing(tmp_path: Path) -> None
strict_report = lint_vault(vault, require_trust_ledger=True, strict_trust=True)
assert strict_report["status"] == "fail"
def _reviewed_then_ignored(tmp_path: Path) -> Path:
vault = tmp_path / "vault"
_page(vault, "concepts/alpha.md")
_page(vault, "private/hidden.md")
_write_ledger(vault)
(vault / ".okignore").write_text("private/\n", encoding="utf-8")
return vault
def test_check_counts_a_reviewed_page_ignored_later_without_naming_it(tmp_path: Path) -> None:
vault = _reviewed_then_ignored(tmp_path)
report = check_trust_ledger(vault)
# Still a warning: a page leaving the review gate has to stay visible.
assert report["status"] == "warn"
assert report["ignored_entries"] == 1
assert report["counts"]["ignored_entries"] == 1
assert report["missing_pages"] == []
assert "hidden" not in json.dumps(report)
def test_a_deleted_page_is_still_reported_missing_by_name(tmp_path: Path) -> None:
vault = _reviewed_then_ignored(tmp_path)
(vault / "concepts" / "alpha.md").unlink()
report = check_trust_ledger(vault)
assert report["missing_pages"] == [{"page": "concepts/alpha.md", "reason": "reviewed_page_missing"}]
assert report["ignored_entries"] == 1
def test_partial_review_prunes_ignored_entries_without_changing_other_reviews(tmp_path):
vault = _reviewed_then_ignored(tmp_path)
ledger_path = vault / "_meta/trust-ledger.json"
before = json.loads(ledger_path.read_text())
updated = update_trust_ledger(
vault, ledger_path, reviewed_at="2026-11-07T00:00:00Z",
page_paths=["concepts/alpha.md"],
)
assert updated["removed_ignored"] == 1
assert set(updated["pages"]) == {"concepts/alpha.md"}
assert updated["pages"]["concepts/alpha.md"]["material_fingerprint"] == before["pages"]["concepts/alpha.md"]["material_fingerprint"]
write_trust_ledger(ledger_path, updated)
assert check_trust_ledger(vault)["ignored_entries"] == 0
+28
View File
@@ -83,3 +83,31 @@ def test_staging_cli_conflict_keeps_reviewed_and_live_files(tmp_path, capsys):
]) == 9
assert live.read_text() == "Concurrent live update"
assert staged.read_text() == "Reviewed proposal"
@pytest.mark.parametrize("shape", ["dict", "list"])
def test_source_coverage_accepts_local_archive_metadata_and_preserves_manifest(tmp_path, shape):
page = tmp_path / "concepts/a.md"
page.parent.mkdir()
page.write_text("---\ntitle: A\n---\n")
entries = [
{"path": "original.pdf", "archive_path": "_sources/archive/a.pdf",
"pages_produced": ["concepts/a.md"], "bjd_part_numbers": ["BJD-123"]},
{"path": "lost.pdf", "pages_updated": ["concepts/deleted.md"]},
{"path": "legacy.pdf", "pages_created": 2},
]
manifest = tmp_path / ".manifest.json"
manifest.write_text(json.dumps({"sources": {e["path"]: e for e in entries} if shape == "dict" else entries}))
before = manifest.read_bytes()
report = lint_vault(tmp_path, require_trust_ledger=False)
assert report["findings"]["uncovered_sources"] == [
{"source": "lost.pdf", "issue": "pages_missing", "missing": ["concepts/deleted.md"]}
]
assert manifest.read_bytes() == before
def test_lint_cli_exposes_source_coverage_in_json_and_strict_exit(tmp_path, capsys):
(tmp_path / ".manifest.json").write_text(json.dumps({"sources": {"lost.pdf": {"pages_produced": []}}}))
assert main(["lint", str(tmp_path), "--json", "--strict"]) == 1
report = json.loads(capsys.readouterr().out)
assert report["stats"]["findings"]["uncovered_sources"] == 1