write_page
Create or refresh source-backed Wenlan wiki pages from conversation content, updating existing pages in place without breaking links.
Instructions
Create or refresh a wiki page. When the user asks to turn something from this conversation into a page, call write_page with a title and the content; source_memory_ids are optional. This write can replace an existing page: omit page_id to create a new page (title required); with enough cited sources it lands as a distilled page, otherwise as an authored page. The daemon writes the DB row and the on-disk /.md projection atomically (default ~/.wenlan/pages/, slug made unique on collision). Pass page_id (from the stale_pages block in distill output) to refresh that page in place — replaces content + source_memory_ids + optional summary, clears stale_reason, preserves page_id and created_at, bumps version monotonically so external [[wikilinks]] keep working. Never delete_page + recreate to refresh: that churns ids and loses version history. To change an existing page's title at the user's explicit request, use rename_page; refresh keeps the existing title. Before a refresh, read_page and pass its page.version as expected_version: if the page moved on, the write is refused with nothing changed, so re-read and retry. Without expected_version, a refresh of a page the user wrote or edited is refused the same way. A page with review_required set stages every refresh as a revision card for the user. basis [{page_id, version}] lists notes relied on (versions from read_page); a changed one lands pending (see page_basis). minor: true = small edit. code_basis [{repo_root, path, line_start, line_end}]: code lines relied on (see page_code_basis). Refresh is not available over remote HTTP MCP transport (local stdio only).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| basis | No | Other notes (wiki pages) this page relies on, each as {page_id, version} where version is that note's page.version from your read_page. Use it for notes only; memories go in source_memory_ids and a note's page id never does. A listed note counts as confirmed only if it is still at that version; if it changed after your read it is recorded as pending instead. Existing bases of the page stay as they are. The reply lists the page's bases after the write. | |
| minor | No | Refresh only: true marks this write as a small edit (typo, formatting, a one-word fix), so pages relying on this one are told the change was minor. It never hides the change from them. | |
| space | No | Topic scope (e.g. 'origin', 'work'). Optional. Create only. | |
| title | No | Short noun phrase that names the page (e.g. 'Wenlan daemon architecture'). Required when creating; ignored on refresh. | |
| content | Yes | Markdown body — 3-7 paragraphs of wiki prose with [[wikilinks]]. Do not cite source ids inline; pass them in source_memory_ids and the daemon attaches provenance automatically. | |
| page_id | No | Omit to create a new page. Pass an existing page id (e.g. 'page_abc', from the `stale_pages` block in distill output) to refresh that page in place. | |
| session | No | Your AI session as tool:id, e.g. claude-code:<session id>; links what you write back to this conversation. | |
| summary | No | Optional one-sentence summary — the durable claim. On refresh: omit to keep the existing summary; pass empty string to clear it. | |
| entity_id | No | Optional entity_id (e.g. 'ent_abc') to anchor the page to a knowledge-graph entity. Create only. | |
| code_basis | No | Lines of code this note relies on; Wenlan tells you when they change. Each entry is {repo_root, path, line_start, line_end}: repo_root is the absolute path of the repository, path is relative to it with `/` separators (no `..`), lines are 1-based and inclusive. Wenlan reads the file when you write; an unreadable file, a path outside the repository or lines past the end of the file refuse the whole write. Entries are added to the page's existing code bases (naming one again re-anchors it as `ok`). Local stdio only. The reply lists the page's code bases after the write. | |
| expected_version | No | Refresh only: pass page.version from read_page. When the page has moved on, the write is refused and nothing changes; re-read the page with read_page and retry. A refresh of a page the user wrote or edited lands directly with it and is refused without it. | |
| source_memory_ids | No | Memory source_ids the page is distilled from. Memories only: a note's page id is refused here, pass it in `basis`. Optional: pass them when the page is built from captured memories, because they are its traceability (the daemon attaches provenance from them). Omit them for a page written from the conversation itself. On refresh, carry the page's existing list through; a page that has sources refuses an empty list. |