--- name: wiki-publish metadata: version: "0.24.9" description: Publish docs (roadmap, plans, user guide, status) to the team's configured wiki. Use when asked to publish/sync docs to the wiki, after cutting a roadmap snapshot, or when a plan/status report should be visible outside the repo. --- # Wiki publish No per-system code ships with this skill. Read the config, then use whatever tooling exists for that system — you already know these platforms. ## 0. The publish manifest drives the publish set If `docs/.index/publish-manifest.json` exists (generated by `worklog ia-render`), it IS the publish set — use it instead of the implicit default set in §4. For each manifest page: - `source` is the file to publish, `page_name` the wiki page name, `title` the display title. The `sidebar` entry publishes as `_Sidebar.md`. - `render: "as-is"` — publish the file as-is (frontmatter-strip rules of §3 still apply). - `render: "doc+banner"` — strip frontmatter per §3, then prepend the page's `banner` line plus a blank line. Banners are publish-time renders; never write them into `docs/` sources (frozen docs stay frozen). - **Skip rule uses `render_hash`, not `source_hash`:** publish a page when the ledger entry's `render_hash` differs from the manifest's (or the ledger has none), and record `render_hash` alongside `source_hash` in the ledger entry afterwards. This is deliberate: a frozen page's source never changes, but its banner can (e.g. a plan becomes superseded) — the rendered overlay must reach the wiki even though the source is untouched. - **The frozen guard reads the manifest's `source_hash`, and that is a BODY hash.** `frozen: true` still guards the source: if a frozen page's `source_hash` differs from the ledger's, stop and report it — that is a frozen-doc edit, not a render update. Take the value from the manifest; never hash the file yourself. The manifest hashes the doc **below its front matter**, because you strip front matter anyway (§3), so two files differing only there publish identically. That makes this guard mean *the prose changed* — the thing §15.8/§15.9 protects — instead of firing on every metadata stamp the normalizer, `adr.mark_superseded`, or a provenance backfill writes. - **Never publish `docs/.index/` internals**: only `docs/.index/rendered/*.md` listed in the manifest reaches the wiki. The JSON/YAML files (inventory, graph, manifest, aliases, sidecars) are internal join data. Run `worklog ia-index` first if the manifest is stale (`worklog ia-render --check` tells you). ## 1. Read the config Read the `wiki:` block in `.work/config.yml`. `system` names the wiki: `github-wiki`, `gitlab-wiki`, `ado-wiki`, `confluence`, `other`, or `none`. If it is `none` or absent, say so and stop — there is nothing to publish to. The enum is advisory — `other` is any wiki not listed (Notion, MediaWiki, a docs site): set it, name the real system in `options:`, and resolve the tooling at runtime like any other system below. ## 2. Pick the tooling Use whatever is available for the configured system, in order of preference: a CLI already installed, an MCP server, or an installed skill. ### github-wiki `gh`/`git`: clone `.wiki.git` into the gitignored `.work/wiki-checkout/`, copy page files in, commit, push. Page namespace is flat — no directories: the filename IS the page name (`User-Guide.md` → "User Guide"). The wiki repo's default branch is `master`. Cross-page links use `[[Page-Name]]` syntax. Pull before pushing — the checkout is a cache; pages may have been edited in the web UI. ### gitlab-wiki Also a git repo: clone `.wiki.git`, then copy/commit/push exactly as for github-wiki. Or use REST via `glab api projects/:id/wikis`. The page slug is the filename (minus `.md`). Unlike GitHub, GitLab wikis support directories, so nested paths work. ### ado-wiki Two kinds. A **project wiki** is backed by a hidden git repo — clone it via the wiki's git URL and push like any git-backed wiki. A **code wiki** publishes a folder on a branch — if the team uses one over `docs/`, committing docs IS publishing; still record ledger entries. For the REST path: `az devops wiki page create/update --wiki --path --content`. Page paths are hierarchical (`/Parent/Child`). ### confluence Needs a space key and parent page id — read them from `wiki.options` in the config. Prefer an Atlassian MCP server or an installed Confluence skill; otherwise use REST (`/wiki/rest/api/content`), which takes storage format — convert the markdown, or use a converter the team already has. If no conversion tooling exists, say so and ask rather than publishing mangled markup. Page identity is the content id — store it as `page_id` in the ledger entry. The version number increments on every update — store it as `rev`. If tooling is missing, RESEARCH it (docs/web) and tell the human what to install — do not guess blindly. These are mainstream systems; rely on model knowledge plus live exploration, not shipped integration code. ## 3. Strip frontmatter for Gollum-style wikis Plans, ADRs, status reports, and design docs carry a YAML frontmatter block (`---` ... `---`) as their machine-readable source of truth — never touch that in `docs/`. But Gollum (GitHub wiki, and any other Gollum-style wiki) renders it as raw text instead of parsing it, so the page opens with an ugly `---` block up top. Fix it in the copy, not the source: for `github-wiki` (and `other` systems that are Gollum-backed), when writing a page into the wiki checkout, strip the leading frontmatter block first — only when the file starts with a `---` line at byte 0, delete through the next line that is exactly `---`, and write what remains. A doc with no frontmatter, or where `---` appears later in the body, is untouched. `gitlab-wiki`, `ado-wiki`, and `confluence` understand or can be given frontmatter, so keep or adapt it per platform instead of stripping. ## 4. Maintain the ledger `.work/published.json` maps logical keys to what was published: {"": {"source": "repo/path.md", "url": ..., "rev": ..., "source_hash": "the manifest's body hash", "render_hash": "the manifest's render_hash"}} Entries carry a `source` field (the repo path of the file) so the publish set is self-describing. The DEFAULT publish set is always: the live roadmap (`docs/roadmap.md`), every plan in `docs/plans/`, every roadmap snapshot in `docs/roadmap/`, every ADR in `docs/adr/` — republish on hash change (status flips must reach the wiki), page name `ADR-NNNN-slug`, ledger key `adr/NNNN-slug` — plus anything registered via `worklog wiki-add`. Plans and snapshots publish once (frozen); the roadmap and ADRs re-publish on hash change. To opt an arbitrary file in, register it: `worklog wiki-add --key K --title T`. When a manifest exists (§0) it is the authority: copy its `source_hash` and `render_hash` into the ledger rather than hashing files yourself. Only when there is no manifest entry — a file registered via `worklog wiki-add`, say — hash it directly (`sha256`, first 12 hex chars, of the whole file). If the ledger entry's hash matches, skip it — already published. After publishing, update the entry with the page url, the wiki revision (e.g. wiki commit sha), and the new hash. Commit `published.json` together with the docs it describes. ## 5. Ledger fields across systems The ledger shape is fixed by spec §9.3; systems just fill it differently. `url` is always the page's browse URL. - **git-backed wikis** (github-wiki, gitlab-wiki, ADO project wiki) — `rev` = wiki commit sha, `page_id` = filename stem (`User-Guide`). - **confluence** — `rev` = page version number, `page_id` = content id. - **ado-wiki via REST** — `rev` = the ETag/version from the response, `page_id` = the page path. ## 6. Page naming Derive the wiki page name from the doc title. Keep the title stable per logical key — renaming a page breaks inbound links. ## 7. One-time init Surface one-time setup steps to the human; never work around them silently. Example: a GitHub wiki's `.wiki.git` does not exist until someone clicks "Create the first page" in the repo's wiki tab — if the clone/push fails with not-found, ask the human to do that once, then retry. ## 8. Frozen rules Snapshots, plans, status reports, and dated design docs/code walkthroughs publish once and are never re-published. The live Roadmap page, ADRs, and `current_design_doc` / `current_code_walkthrough` are the exceptions: re-publish whenever the source hash changes — for an ADR, a status flip (proposed→accepted, accepted→superseded) is exactly the change that must reach the wiki. ## 9. Diagram assets GitHub wiki renders fenced `mermaid` blocks. It does not render PlantUML source. Confluence does not reliably render either. When a page under `docs/designs/` (or a requirements doc) links an image in `docs/diagrams/`: - **github-wiki**: copy the PNG or SVG into the wiki checkout next to the page (flat namespace) or keep a working relative link. A wiki page that points at a missing image is a publish defect. - **confluence**: upload Mermaid and PlantUML images as attachments and replace source fences with the image. Do not ship a mermaid fence as the only Confluence view. - Leave mermaid fences in the GitHub wiki copy. Leave PlantUML as an image plus the `.puml` source in the repo. Missing `docs/diagrams/*.png` (or `.svg`) for a PlantUML leftover type blocks publish. Same for Confluence mermaid images.