mirror of
https://github.com/Ar9av/obsidian-wiki.git
synced 2026-09-14 20:36:34 +08:00
5c2b92587c
`_staging/` promotion existed only as agent instructions in .skills/wiki-stage-commit/SKILL.md — `grep -rn "_staging" obsidian_wiki/` returned nothing. That was fine while an agent was the only actor, but it meant a UI or a CLI could not promote a staged page without writing a second copy of the rules, which is exactly what #208 was trying to avoid. obsidian_wiki/staging.py now owns the parts with one correct answer: list_staged(vault) inventory, classified new / update / patch, with both sides' content revisions pinned promote(...) atomic os.replace to the live path discard(...) move back to _raw/rejected-…, never clobbering an earlier rejection of the same page Promotion is a rename, so the page that lands is byte-for-byte the one that was reviewed: arbitrary frontmatter, prose and wikilinks survive untouched. Judgment stays with the skill. `.patch.md` files are listed but refused by promote() — merging a human-readable diff into a page whose surrounding text may have moved is not mechanical. The revision check is the reason this exists. An agent can write to _staging/ or to the live page while a human is mid-review, so callers pass the hashes they reviewed and get StagingConflict instead of a silent overwrite. pin_live_absent covers the case a bare None cannot express: "there was no live page when I looked." Also: - `obsidian-wiki staging list|promote|discard`, exit 9 on conflict so a caller can tell "re-read and ask again" from "bad input" - server._resolve and the /v1/staging listing now use the shared module instead of their own copies - SKILL.md calls the commands rather than restating the steps Closes #212.