--- name: wiki description: Move wiki pages between a local space and Gitea — fetch a page and everything under it as a local cache, publish a page tree with an update message, list what the wiki holds. Load when the user asks to read/fetch a wiki page, cache a wiki subtree for a discussion, or publish artifacts to the wiki. Organizing artifacts into a page tree (titles, ordering, the index) is /tea:page and needs no network. --- # /tea:wiki — the bridge between a local space and a Gitea wiki One job: translate between `tmp/wiki//` and Gitea's wiki JSON, and carry the result over the wire. Everything about **what a page tree is** — titles, ordering, paths, the index — belongs to `/tea:page` and is imported from there, never redefined here. Transport is `tea api` through `skills/sync/scripts/_gitea.py`: the same login pin, the same pagination, the same payload files. There is no second transport. ## The wiki is flat, and that is the whole design Gitea's wiki is a list of pages, not a tree. Nesting exists only inside a title, as `/`, and Gitea escapes that title into a filename by rules that are its own: | title | `sub_url` | |---|---| | `Abstract Issue` | `Abstract-Issue` | | `zz-probe/child` | `zz-probe%2Fchild.-` | | `Simple Chains/Parked/Chain decisions — DC` | `Simple-Chains%2FParked%2FChain-decisions-%E2%80%94-DC` | **`sub_url` is the identity and is never constructed.** It is read back from the API and stored in the manifest. Building one by hand that is almost right does not fail loudly — it creates a second page and abandons the first. **Never commit a subdirectory into the wiki's git repository.** A real `folder/page.md` is invisible to the API and to the web UI. It is a ghost file. Do not clone the wiki repo to work in; use these scripts. ## Scripts In `/scripts/`. | Script | What it does | |---|---| | `wiki_ls.py [--prefix T]` | what the wiki actually holds — titles, `sub_url`, last commit. One call, no bodies | | `wiki_pull.py [--prefix T] [--space S]` | fetch a page and everything under it into a local space | | `wiki_push.py -m MSG [--prefix T] [PATH…]` | publish; create what is new, update what changed, skip what is not | | `wikimap.py` | md ↔ wiki JSON, pure — not a command | ## Fetching a subtree as a cache "A page and its children" is a prefix test on the title, run against one listing call, followed by one GET per page. There is no tree endpoint and no bulk-body endpoint. ```bash python3 scripts/wiki_ls.py --prefix "Simple Chains" # what is there python3 scripts/wiki_pull.py --prefix "Simple Chains" # cache it locally ``` A pull **overwrites** the local body — a fetch, not a merge. `synced` tells you how old your copy is; re-pull when it matters. Nothing tracks drift. The space defaults to the repo's own `owner/repo`, so a pull with no flags caches this repo's whole wiki into `tmp/wiki///`. ## Publishing ```bash python3 scripts/wiki_push.py -m "Import the simple-chains discussion" --dry-run python3 scripts/wiki_push.py -m "Import the simple-chains discussion" ``` `-m` is required and is the wiki commit message — the only record of why a page changed, and it shows up in `wiki/revisions/`. One operation, one message. Change detection is a hash: a page whose file matches `pushed` is skipped. A page with no `sub_url` is created; one with a `sub_url` is edited in place, using the title **from the manifest** — sending a different title to the edit endpoint is a rename and leaves nothing at the old address. Selection, narrowest first: positional `PATH`-or-`TITLE` arguments (matched exactly), then `--prefix`, then the whole space. **Pushing is additive.** A page deleted locally is not deleted in the wiki. Removing a published page is an explicit act — the web UI, or `tea api --login "$GITEA_LOGIN" -X DELETE repos/{owner}/{repo}/wiki/page/`. ## Order of operations for a fresh tree The index links published pages by `sub_url`, which does not exist until the first push. So: ```bash python3 ../page/scripts/page_import.py --from DIR --prefix "Simple Chains" python3 scripts/wiki_push.py -m "Import the simple-chains discussion" python3 ../page/scripts/page_index.py --prefix "Simple Chains" # now with real links python3 scripts/wiki_push.py -m "Index" ``` ## Linking an issue to a page An issue's `wiki:` field holds page **titles**, not URLs — a title is a name for a document and stays in the domain; the URL is bookkeeping. `wiki_ls.py --titles` prints them one per line, which is what to paste. ## Endpoints, for when a script is not enough Reach for `/tea:use` and `tea api` directly only for what has no script — a delete, or a page's history. | | | |---|---| | list | `GET repos/{owner}/{repo}/wiki/pages` | | read | `GET repos/{owner}/{repo}/wiki/page/{sub_url}` | | create | `POST repos/{owner}/{repo}/wiki/new` — `{title, content_base64, message}` | | edit | `PATCH repos/{owner}/{repo}/wiki/page/{sub_url}` — same body | | delete | `DELETE repos/{owner}/{repo}/wiki/page/{sub_url}` | | history | `GET repos/{owner}/{repo}/wiki/revisions/{sub_url}` | The `tea` CLI has no wiki subcommand. `tea api` is the only route.