---
name: wiki-publish-safely
description: >-
  The hard rules and operational pitfalls for editing Adom Wiki pages
  (wiki.adom.inc) without breaking them, write both storage layers, never
  base64 a text file, versions are immutable, soft-delete blocks re-creation, the
  hero gets clobbered on publish, rate limits, and the non-negotiable verify-in-pup
  step. Read this before AND after any publish, file push, README change, or
  metadata edit. Trigger words: wiki publish broke the page, page shows
  placeholder, readme is gibberish, files tab empty, hero disappeared, hero
  unlinked, UNIQUE constraint pages, immutable version, `adom-wiki pkg` 429, ghost page,
  verify wiki in pup, wiki publish checklist, don't break the wiki page.
---

Parent skill: **adom-wiki-skillpack**

# Publishing to the wiki without breaking the page

Every item here is a real incident that recurs. Treat them as hard rules. The
mechanics live in **wiki-api**; this is the "don't shoot yourself in the foot"
companion.

## The five rules that prevent broken pages

1. **Write BOTH layers, every publish.** Git repo (`POST /files`) *and* package
   registry (`adom-wiki pkg publish`). Only one → the page is broken (placeholder Files
   tab, or a README that won't `adom-wiki pkg install`). See **wiki-anatomy**.

2. **The hero gets clobbered, re-push `page.json` LAST.** `adom-wiki pkg publish`
   overwrites the repo's `page.json` with the package manifest, which has **no
   `hero`**, so the page-header hero is unlinked on every publish. The PNG is NOT
   deleted; only its reference is dropped. **Fix:** publish first, then push a
   *complete* `page.json` (with `hero:{type:"image",path:"screenshots/hero.png"}`,
   title, brief, tags) as the final commit, and confirm
   `GET /api/v1/pages/<slug>` shows `hero_path` set. Full detail → **wiki-hero**.
   The same clobber resets the page **title and brief** to the package values ,
   the complete `page.json` re-push restores those too. Two title traps: (a) put a
   `title` in **package.json** as well, the manifest has none by default, so the
   clobber resets the title to the bare **slug**; (b) the title must be a
   **human, descriptive name, NEVER the slug echo** (`Wiki Hero Image Skill`, not
   `adom-wiki-hero-image`). Cards, search, the homepage, and the screensaver all
   show the title; nobody reads slugs. → **wiki-repo-styles** / **wiki-family**.

3. **Text is plain; only binaries are base64.** Base64-encoding a `.md`/`.json`/
   `.sh` makes the wiki store the base64 string as the file content → README
   renders as gibberish. Images/fonts/archives go base64; everything else plain.

4. **Versions are immutable; never delete-and-recreate.** Once `0.1.0` is
   published it can't be overwritten, `adom-wiki pkg version patch` before republishing
   changed source. And `DELETE /pages/:slug` only *soft*-deletes (sets
   `deleted_at`), after which republishing the same slug fails with
   `UNIQUE constraint failed: pages.owner, pages.slug`. Bump the version instead
   of deleting. (Hard purge exists, `DELETE /pages/<slug>?hard=true`, but it's
   irreversible and rarely the right move.)

5. **Verify with your eyes, open the live page in pup.** After ANY wiki edit
   (publish, file push, metadata/README/hero change, even a one-file fix), open
   the page in a pup window on the user's laptop and screenshot-confirm it
   rendered. Do not report a wiki edit as done from API JSON alone.

   ```bash
   OWNER=john; SLUG=my-page; LAP=AdomLapper   # `adom-desktop status` shows the laptop host
   adom-desktop browser_open_window \
     "{\"sessionId\":\"wiki\",\"profile\":\"wiki\",\"url\":\"https://wiki.adom.inc/$OWNER/$SLUG\"}" \
     --target "$LAP"
   sleep 3
   adom-desktop browser_screenshot '{"sessionId":"wiki","maxWidth":1500}' --target "$LAP"
   # Read the screenshot; confirm it rendered before telling the user it's done.
   ```

   Reuse `sessionId:"wiki"` / `profile:"wiki"` every time so the login persists;
   `browser_navigate` an already-open window rather than spawning new ones.

## Never show the hero twice

The page header renders the hero from `page.json` automatically. **Do NOT also
embed the hero image in the README body**, the human would see the same image
twice, back to back. It's the most common README mistake on the wiki. Inline
README images must be *other* screenshots/diagrams. Before publishing, grep the
README for the hero filename and delete any line that references it. → **wiki-readme**.

## Other gotchas

- **Cloudflare WAF blocks Python urllib/requests without a `User-Agent`** →
  send `User-Agent: `adom-wiki pkg`/2.1.0`. curl sends its own UA and is fine.
- **Publish-only pages create ghost rows.** `adom-wiki pkg publish` without first
  `POST /pages` makes a tarball but no git repo; a later `POST /files` then
  inserts a *second* page row (a duplicate on the listing). Always create the
  page first.
- **Rate limit: ~10 publishes/minute** → HTTP 429. Space them or retry.
- **Search hyphen bug:** FTS reads `-` as a column operator (`chip-fetcher` →
  "no such column: fetcher"). Most slugs have hyphens; expect this until fixed.
- **Inline images need HEAD support** on `/blob/` routes, a known wiki bug means
  `<img>` can 404 on preflight even though the tag is correct. Verify visually.

## The publish checklist

- [ ] `package.json`: version bumped, `files[]` complete, `dependencies` set
- [ ] Page created (first time only) via `POST /pages`
- [ ] `adom-wiki pkg publish` succeeded (tarball in registry)
- [ ] ALL source pushed to git (text plain, binaries base64, UA header)
- [ ] **Complete `page.json` pushed LAST** → `hero_path`, title, brief restored
- [ ] **Title is descriptive, NOT the slug** (and `title` is set in `package.json` too, so publish won't reset it to the slug)
- [ ] README does NOT embed the hero image (page header shows it already)
- [ ] Opened in pup + screenshot read: README renders, Files tab full, hero shows
- [ ] `adom-wiki pkg info <slug>` shows the right version + dependencies
