# Agent's Guide to Wiki

## Agent Guide: Updating BookStack Wiki Pages

This guide outlines how AI agents can directly query, read, edit, and update pages in the self-hosted **BookStack Wiki** (https://wiki.drheck.dev/).

---

## 1. Golden Rules for Agents

> ### 🚨 MANDATORY RULE: READ LIVE CONTENT FIRST BEFORE EDITING
> **NEVER generate or overwrite page content from memory or scratch without first reading the current live page and its latest revisions.**
> Humans frequently make live edits in the BookStack browser interface between agent turns. Overwriting a page without reading its latest `markdown` and `page_revisions` destroys user contributions, custom links, code blocks, and embedded images.
>
> **Every page update MUST follow this sequence:**
> 1. Fetch live markdown to a file via `/home/luke/bin/read-bookstack-page <page_id> <output_file>`.
> 2. Query attached images from the `images` table.
> 3. Incorporate existing content, user edits, and image tags into the updated document.
> 4. Deploy changes with `/home/luke/bin/update-bookstack-page <page_id> <file_path>`.
> 5. Pull down the live rendered page and verify HTML and KaTeX formula output via `/home/luke/bin/verify-bookstack-page <page_id_or_slug>`.

> ### 🚨 MANDATORY RULE: PULL DOWN & VERIFY THE RENDERED PAGE & FORMULAS AFTER EVERY EDIT
> **Mathematical formulas (`$$...$$` and `$...$`), signal chains (`\longrightarrow`), matrices, and TeX output are desired and encouraged across the wiki—but once an edit is made, you MUST pull down the live rendered page and check the output.**
>
> Never assume a formula rendered properly just because the Markdown source looks right or `LENGTH(html)` is non-zero in MariaDB. BookStack's server-side CommonMark parser transforms backslash-punctuation sequences before client-side KaTeX runs, and unquoted shell expansions can corrupt either the page source or the global `app-custom-head` KaTeX loader.
>
> **After every wiki edit, you MUST:**
> 1. Run `/home/luke/bin/verify-bookstack-page <page_id_or_slug>` (also executed automatically by `update-bookstack-page` and `create-bookstack-page`), which pulls down the live rendered page over HTTPS (`https://wiki.drheck.dev/books/<book>/page/<slug>`) and validates:
>    - Every inline `<script>` and the global `app-custom-head` KaTeX auto-render loader in `<head>` (`vm.Script` syntax check + intact `$$` and `$` delimiter verification).
>    - Every `$$...$$` display formula and `$...$` inline formula in the rendered `.page-content` DOM using real KaTeX `0.16.11` (`katex.renderToString` with `throwOnError: true, strict: 'error'`).
>    - Zero unrendered TeX macros (`\text{...}`, `\longrightarrow`, `\frac{...}`, `\begin{...}`), stray `$$` delimiters, CommonMark-stripped matrix row breaks (`\\`), CommonMark-stripped percent signs (`\%`), or accidental `$` prose collisions.
> 2. Inspect the live rendered HTML of the edited section via `curl -skL https://wiki.drheck.dev/books/<book_slug>/page/<page_slug>` to confirm clean rendering.

> ### 🚨 ABSTRACT DATABASE-INTERNAL IDS FROM USER-FACING TEXT
> **Never include internal database IDs or object identifiers in user-facing page bodies, changelogs, or documentation summaries.**
> Database IDs are internal implementation details strictly for CLI helper execution (`read-bookstack-page <id>`, `update-bookstack-page <id>`). Humans navigate the wiki by title and URL slug. Always use human-readable titles, book names, and standard markdown hyperlinks (e.g. `[Setup Detail](https://wiki.drheck.dev/books/setup-detail)`), never raw numeric IDs.

> ### 🚨 DUAL STORAGE RULE (`markdown` vs `html`)
> BookStack stores page source in the `entity_page_data` table:
> - **`markdown`**: Source text loaded by BookStack when a page is opened in the browser editor.
> - **`html`**: Rendered HTML displayed to public visitors on the website.
>
> **Never update `html` alone!** Updating `html` alone causes the editor to load the outdated `markdown` column and wipe out HTML changes upon saving. Agents must update the **`markdown`** source via the official helper scripts.

---

## 2. Environment & Database Access

- **Service Host:** `ul` (`ul.drheck.dev`)
- **Rootless Podman Container (Database):** `bookstack_db` (MariaDB, running under `docker-data`, `UID 1100`)
- **Rootless Podman Container (Web/App):** `bookstack` (runs PHP-FPM as user `abc`)
- **Env File:** `/data/docker/bookstack/.env`
- **Database Name:** `bookstackapp`

> **Note on Execution Context:** The helper utilities interact directly with local rootless Podman containers under `docker-data` (`UID 1100`) on `ul` (executing `artisan` as container user `abc` with `HOME=/config` so root-owned cache/log files are never created). If the agent is running on another workstation, execute helper commands over SSH to `ul` using single-quoted outer SSH blocks or heredocs (`ssh ul << 'EOF'`) so `$` and `$$` in LaTeX formulas are never expanded by the local shell.

---

## 3. Recommended Workflow & Utilities

Official CLI utilities in `/home/luke/bin/` on host `ul` eliminate shell quoting bugs, SQL newline escaping artifacts, and cache desync:

### Step 1: Find Page ID or Book ID by Slug or Keyword
```bash
/home/luke/bin/find-bookstack-page <search_term>
```
*Output:*
```text
id	name			slug			type
31	System Change log	system-change-log	page
```

### Step 2: Export Live Markdown to a File (MANDATORY)
Export the live markdown directly to a clean file using the base64-safe reader:
```bash
/home/luke/bin/read-bookstack-page <page_id> /tmp/page_<page_id>.md
```
*(Do NOT use raw `mariadb -e "SELECT markdown..."` queries, as the MariaDB CLI client escapes newlines into literal `\n` strings).*

### Step 3: Check Attached Images & Revisions
**Check image attachments:**
```bash
(cd /tmp && sudo -u docker-data HOME=/home/docker-data XDG_RUNTIME_DIR=/run/user/1100 podman exec bookstack_db mariadb \
  -ubookstack -p"$(sudo grep DB_PASSWORD /data/docker/bookstack/.env | cut -d= -f2)" \
  bookstackapp -e "SELECT id, name, url FROM images WHERE uploaded_to=<page_id>;")
```

### Step 4: Edit Content Locally in the File
Modify `/tmp/page_<page_id>.md`, ensuring that all existing user edits, links, and image references (`![alt](url)`) are preserved.

### Step 5: Update Existing Page or Create New Page

**To update an existing page:**
```bash
/home/luke/bin/update-bookstack-page <page_id> /tmp/page_<page_id>.md
```

**To create a new page in a book:**
```bash
/home/luke/bin/create-bookstack-page <book_id> "<page_title>" <file_path>
```

These helpers Base64-encode content, invoke BookStack's native PHP `PageContent` models inside Docker as user `abc` (`artisan tinker`), compile both `markdown` and `html` columns, update revision tracking, clear the application and view caches, and automatically run `/home/luke/bin/verify-bookstack-page` against the live rendered URL.

Remember to clean up your temporary file afterwards (`rm -f /tmp/page_<page_id>.md`).

---

## 4. Mandatory Rendered-Page & Formula Verification

After every page update or creation, verify the live rendered output over HTTPS using `/home/luke/bin/verify-bookstack-page`:

```bash
/home/luke/bin/verify-bookstack-page <page_id_or_slug_or_url>
```

*Example Output:*
```text
Verified live rendered page: https://wiki.drheck.dev/books/system-setup/page/subocr-service
  Title: subocr service | Math blocks verified: 2 display ($$...$$), 7 inline ($...$)
  STATUS: PASS (0 script errors, 0 KaTeX errors, 0 unrendered TeX blocks)
```

Also inspect the rendered HTML of any modified formulas or sections directly from the live web server:
```bash
curl -skL https://wiki.drheck.dev/books/<book_slug>/page/<page_slug> | grep -C 3 "<search_term>"
```

<p class="callout warning"><strong>Why Database Length Checks Are Insufficient:</strong> Checking only <code>SELECT LENGTH(markdown), LENGTH(html) FROM entity_page_data</code> does not detect CommonMark backslash stripping (such as <code>\\</code> turned into <code>\ </code> or <code>\%</code> turned into a TeX comment <code>%</code>), Markdown <code>&lt;em&gt;</code> tags splitting a formula across DOM text nodes, or JavaScript syntax errors in <code>app-custom-head</code>. Always verify the live rendered page.</p>

---

## 5. Advanced Features & Typography Standards for Agents

BookStack on `ul` is enhanced with rich typographical, mathematical, and layout capabilities. Agents are encouraged to leverage these features:

### 5.1 KaTeX TeX Mathematical Engine (Globally Enabled)
A client-side KaTeX (`0.16.11`) rendering engine is active across all wiki pages, paired with server-side KaTeX verification in `/home/luke/bin/verify-bookstack-page`.

* **Display Equations (Block Math)**: Enclose in `$$ ... $$` on their own lines with blank lines before and after:
  ```latex
  $$\text{FREQ} = \frac{433,920,000}{24,000,000} \times 2^{16} = 1,184,883 = \mathbf{0x121473}$$
  ```
* **Inline Math**: Enclose in single `$ ... $` directly within sentences:
  `$T_e = 291.27\text{ }\mu\text{s}$`
* **Signal Chains & Architecture Pipelines**: Use `\longrightarrow` with `\text{...}` for hardware, DSP, and ML pipelines:
  ```latex
  $$\text{Video Frame } I(t) \longrightarrow \text{PP-OCRv5 (MIGraphX FP32)} \longrightarrow \text{Qwen2.5-32B (ROCm)} \longrightarrow \text{UniDic + JMdict/JLPT Study View}$$
  ```
* **Matrix & `cases` Row Breaks Require `\\\\` (Four Backslashes) or `\cr` in Markdown**:
  Because BookStack's server-side CommonMark parser unescapes `\\` into a single `\` before KaTeX runs, writing `\\` in Markdown produces `\ ` (a TeX space) in HTML and collapses multi-row matrices onto a single line. Always write `\\\\` (four backslashes) or `\cr` in Markdown so the rendered HTML contains `\\`:
  ```latex
  $$\begin{pmatrix} y_1 \\\\ y_2 \end{pmatrix} = \begin{bmatrix} a_{11} & a_{12} \\\\ a_{21} & a_{22} \end{bmatrix} \begin{pmatrix} x_1 \\\\ x_2 \end{pmatrix}$$
  ```
* **Percent Signs Inside Math Require `\\\%` in Markdown**:
  CommonMark unescapes `\%` into `%` in HTML. In TeX/KaTeX, an unescaped `%` is a comment character that swallows the `%` symbol and everything up to the closing `$`. Always write `\\\%` in Markdown (e.g. `$\le 1\\%$`) so the rendered HTML passes `\%` to KaTeX.
* **Subscript / Underscore Safety**: Do not put multiple unescaped underscores on the same line in LaTeX (e.g. `\text{DRATE_M}...\text{DRATE_E}`), as CommonMark will interpret them as Markdown italics (`<em>...</em>`) and split the DOM text node so KaTeX cannot match the closing `$`. Use hyphens (e.g. `\text{DRATE-M}`) or single subscripts (`x_1`).
* **No Backslash-Punctuation Spacing Macros (`\;`, `\,`, `\!`)**: Never use backslash-punctuation spacing commands inside Markdown math blocks. CommonMark strips backslashes before ASCII punctuation characters prior to client-side KaTeX rendering, turning `\;` into a literal `;` and `\,` into a literal `,`. Always use alphabetic TeX spacing macros (`\quad`, `\qquad`, `\text{ }`) or rely on built-in relation spacing around `\longrightarrow`.
* **Wrap Shell/Nginx Variables & Multiple Currency Amounts Carefully**: In prose outside code blocks, always wrap `$variable` names (e.g. `` `$host` ``, `` `$proxy_add_x_forwarded_for` ``) in backticks so KaTeX does not pair two `$` signs in the same paragraph as an inline math expression.

---

### 5.2 Native BookStack Callout Banners
Use BookStack's native HTML callout classes for colored, professional alert callouts:

```html
<p class="callout info"><strong>Info Note:</strong> Background context and operational instructions.</p>
<p class="callout success"><strong>Success:</strong> Empirical tests verified with zero errors.</p>
<p class="callout warning"><strong>Warning:</strong> Ensure Word Clock is 75Ω terminated on the final device.</p>
<p class="callout danger"><strong>Danger / Critical:</strong> Never run recursive find commands on host ul.</p>
```

---

### 5.3 Japanese Typography & Furigana (Ruby Text)
HTML5 Ruby annotations are fully supported in page bodies:

* **Whole-word Furigana**: `<ruby>漢字<rt>かんじ</rt></ruby>`
* **Per-character Furigana**: `<ruby>振<rt>ふ</rt>り<rt></rt>仮<rt>が</rt>名<rt>な</rt></ruby>`
* **Japanese in TeX Math**: `$$\text{周波数 } f = 433.92\text{ MHz}$$`

---

### 5.4 Collapsible Accordions (`<details>`)
Use collapsible details to tuck away long raw data logs, register dumps, or secondary tables:

```html
<details>
  <summary><strong>Click to expand technical registers</strong></summary>
  <p>Detailed register addresses and bitfield descriptions go here.</p>
</details>
```

---

### 5.5 High-Resolution Gallery Images with Lightbox Links
To embed images stored in the BookStack gallery with centering, scaling, and lightbox popup support:

```html
<p align="center">
  <a href="https://wiki.drheck.dev/uploads/images/gallery/YYYY-MM/image-name.jpg" target="_blank">
    <img src="https://wiki.drheck.dev/uploads/images/gallery/YYYY-MM/image-name.jpg" alt="Description" width="65%" style="border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.15); display: block; margin: 0 auto;">
  </a>
  <em style="display: block; text-align: center; margin-top: 6px; font-size: 0.9em; color: #666;">Figure 1: Descriptive caption.</em>
</p>
```

---

### 5.6 Comprehensive Capabilities Reference
For an exhaustive cheat sheet, math examples, and live test cases, refer to:
📖 **[Meta: Wiki Capabilities, TeX Math & Typography Reference](https://wiki.drheck.dev/books/wiki/page/meta-wiki-capabilities-tex-math-typography-reference)**

---

## 6. Critical Operational Gotchas for Agents

1. **Always Pull Down & Verify the Live Rendered Page**: Run `/home/luke/bin/verify-bookstack-page <page_id_or_slug>` after every edit to verify live HTTPS delivery, `<script>` syntax in `app-custom-head`, and strict KaTeX compilation of every `$$...$$` and `$...$` formula.
2. **Never Expose Internal Database IDs in Documentation**: Do not write internal numeric book or page IDs in user-facing text, changelogs, or documentation summaries. Always use human-readable titles and standard hyperlinks.
3. **Never Parse SQL Output or Update `app-custom-head` via Double-Quoted Shell Strings**: Double-quoted bash strings (`ssh ul "..."` or `mariadb -e "..."`) strip single quotes and expand `$$` into the bash PID, which corrupts both LaTeX formulas and the global `app-custom-head` KaTeX loader. Always use `/home/luke/bin/read-bookstack-page`, `/home/luke/bin/update-bookstack-page`, or hex/base64-encoded payloads.
4. **Strip Top-Level `# <Page Title>` Headers**: BookStack renders the page title as an `<h1>` header automatically. Strip `# <Page Title>` from markdown source to prevent duplicate headers.
5. **Preserve Attached Images**: Always check for image links before overwriting.
6. **Execute `artisan` as User `abc` (`-u abc -e HOME=/config -w /app/www`)**: Running `artisan` as `root` creates root-owned cache/log files in `/config/www/framework/cache` and `/config/log/bookstack/laravel.log`, causing `php-fpm` (`abc`) to return HTTP 500 errors.
7. **CommonMark Escaping Inside KaTeX**: Use `\\\\` (or `\cr`) for matrix/cases row breaks, `\\\%` for literal percent signs inside math, and `\quad`/`\qquad`/`\text{ }` instead of `\;`/`\,`/`\!`.
