Fixes#178. sha256_dir() used str(fp.relative_to(path)), which yields
backslash-separated paths on Windows and forward-slash on POSIX, and sorted
entries by that same OS-native string. Both the hash input and the iteration
order now use as_posix(), so a directory source hashes identically across
platforms and unchanged vaults no longer re-trigger incremental ingest after
a cross-platform sync.
cache-check / cache-update assumed a dict-keyed manifest with bare hex
hashes, but the wiki-ingest skill writes 'sources' as a list of entry
objects with sha256:-prefixed content_hash and vault-relative paths.
Against a skill-built manifest the commands crashed, then (once past the
crash) reported every file as modified/new. Both shapes occur in real
vaults.
- _load/_iter: read both dict- and list-shaped 'sources' transparently
- compare content_hash prefix-insensitively (strip optional algo: prefix)
- match paths across raw / absolute / vault-relative forms
- update_source edits in place, preserving manifest shape, duplicate-path
entries, skill-written fields, and top-level keys (stats/version)
- don't flag URL / pseudo-path source keys as missing-on-disk
- add regression tests covering all four failure modes from the issue
check_sources only matched a manifest entry by the passed key or its
abspath, and detected missing files with Path(key).exists() against CWD.
When the manifest stored vault-relative keys (e.g. _raw/articles/foo.md),
callers passing an absolute path got 'new' instead of 'unchanged', and
every relative key was reported 'missing' when CWD != vault root — so the
docstring's documented abs-or-rel key support was unusable.
Also try the vault-relative form on lookup, and resolve relative manifest
keys against the vault root when checking existence. Add relative-key
tests to close the CI gap (every prior test used absolute keys).
Fixes#136
Replaces the manual sha256sum shell dance with a dedicated Python module
and three CLI subcommands. Pure stdlib — no new runtime dependencies.
- New obsidian_wiki/cache.py: sha256_file/sha256_dir (chunked, memory-safe),
check_sources() classifies a list of paths as new/modified/unchanged/missing
vs .manifest.json; update_source() records hash + pages_produced + timestamp
after a successful ingest.
- CLI: cache-check <vault> <sources...> → JSON classification
cache-update <vault> <source> [--pages ...] → write hash to manifest
cache-hash <path> → just compute and return SHA-256
- wiki-ingest SKILL.md updated: append-mode section now uses cache-check /
cache-update instead of platform-specific sha256sum invocations. Falls back
to the old manual approach if obsidian-wiki is not installed.
- 25 new tests covering hash stability, mtime-independence, manifest round-trips,
and all three CLI commands.