All notable changes to Void 2.0 are documented here.
Format: [Keep a Changelog](https://keepachangelog.com).
## 2.0.0-alpha.20 — Page ordering + sectioned space view
- **Explicit page ordering** (`migration 020`, `lib/db/repos/pages.js`): pages gain a `position integer` column; `listBySpace` now orders `position, title` instead of alphabetical-only, with a covering index `(space_id, position, title)`. `position` is patchable via `PUT /api/pages/:id`. Backfills all rows to `0` (preserves prior title order until positions are set).
- **Sectioned page tree** (`public/views/space.js`): the flat pages table is replaced by a `parent_id`-grouped tree — top-level pages render as section headers with their children/grandchildren nested. Backward-compatible with flat (un-nested) spaces. Enables the Wiki to read as ordered, sectioned documentation rather than an alphabetical dump.
- **Whisper on GPU with graceful CPU fallback** (`workers/void_workers/model.py`): the STT worker uses the in-container NVIDIA driver on the GPU node, and **falls back to CPU on any load failure** (e.g. shared-card VRAM exhaustion) so a transcription never hard-fails. (Passthrough alone gave device nodes but no `libcuda` — the matching userspace driver was installed inside CT 311; see [[gpu-cpu-fallback-for-ha]].)
- **Cooperative GPU sharing with Ollama** (`workers/void_workers/gpu.py`): before loading Whisper on CUDA, the worker asks the co-resident Ollama (CT 102, same A2000) to unload its models (`GET /api/ps` + `POST /api/generate keep_alive:0`) and waits for the card to clear; Ollama reloads on its next request. Best-effort, stdlib-only; toggle `OLLAMA_FREE_BEFORE_STT`, endpoint `OLLAMA_URL`.
# Void Docs Consolidation & Wiki Restructure — Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** Collapse the Void's 7 overlapping spaces into 3 meaningful ones (Wiki / The Void / Bookmarks), turn the Wiki into an ordered, sectioned "traditional lab documentation" area that is the single source of truth, preserve the Void 1.x record + doc lineage, and retire BookStack to a passive secondary mirror.
**Architecture:** Most work is data manipulation on the **prod** Postgres DB (`void` @ `192.168.1.215`). One small code change adds page ordering + sectioned rendering to the `void-v2` app. Pure structural moves (space/parent/position changes, deletes) are done via SQL transactions; content **merges** (where two copies of a doc diverge) are done through the Void web page-editor so `body_html` + embeddings regenerate. Lineage between projects (The Void) and service docs (Wiki) is expressed with `entity_links`.
**Tech Stack:** PostgreSQL 16 + pgvector (prod DB on CT 310 `.215`), Node 22 / Express app (`void-v2`, CT 311 `.216`), `node lib/db/migrate.js up`, deploy via `deploy/push.sh`. PVE snapshots for safety (CT 310 + 311 on host Z).
**Authoritative reference data** (gathered 2026-06-05; re-verify counts before destructive steps):
- Wiki root page: slug `hynesy-homelab`, title "Hynesy Homelab" (all 23 other wiki pages are its direct children).
- DB creds for this work: `DATABASE_URL` in `/project/src/void-v2/.env` (`postgres://void:…@192.168.1.215:5432/void`). Prod app OWNER_TOKEN lives in `/opt/void-server/.env` on CT 311 (`.216`) — fetch at execution for API edits (the `.env` token in the repo is dev-only and is rejected by prod).
## Pre-flight verdict table (void1 ↔ wiki duplicates)
Classification computed by line-diff on 2026-06-05. Drives Task 5. "Drop v1" = delete the void1 copy, wiki copy is canonical. "Merge" = fold void1-only facts into the wiki copy first.
| Claude LXC deployer | (intra-v1 dup of agentic.sh, same md5) | EXACT DUP | drop v1 (pure cruft) |
void1 pages with **no** wiki counterpart (these are Void-app dev docs, salvaged in Task 6, not deleted): Active Projects Status, Agent Roster & Personas, Cron Tasks & Schedules, Deployment Guide, Path B — Build Log, Security Posture & Known Issues, The Void — Architecture & Agent System, The Void — Dashboard Progress (2026-05-14), Homelab Topology, Dashboard rebuild & Orthos overhaul (2026-05-16, also in wiki — moves to The Void, removed from wiki).
---
## Helper: SQL shell used throughout
All SQL steps assume this is exported in the working shell:
Expected: a >0-byte custom-format dump. (`mkdir -p /project/backups` first if missing.)
- [ ]**Step 3: Record current counts as the rollback baseline**
Run:
```bash
Q -c "SELECT s.slug, (SELECT count(*) FROM pages p WHERE p.space_id=s.id) pages,
(SELECT count(*) FROM projects pr WHERE pr.space_id=s.id) projects
FROM spaces s ORDER BY s.slug;"
```
Expected: matches the inventory in this plan's header (void 1/3, void1 25/17, wiki 24/0, plans 6/0, void3 8/0, bookmarks 0/0, external-research 0/0). If it does **not** match, STOP — the data drifted; re-audit before proceeding.
---
## Phase 1 — Page ordering foundation (code)
This is the only code change. It gives every space a stable, intentional order instead of alphabetical-by-title, which is the root cause of "Overview is buried."
FROM pages WHERE space_id=$1 ORDER BY position, title`,[space_id]
);
returnrows;
}
```
- [ ]**Step 5: Allow `position` through update**
In `lib/db/repos/pages.js``update()`, add `'position'` to the updatable `fields` array (currently `['slug','title','body_md','body_html','parent_id','embedding']`):
Currently `space.js` renders pages as a single flat table. Change it to render a **page tree**: top-level pages (no parent, or the space's root page) as section headers, their children indented beneath. Backward-compatible — flat spaces (all pages parent-null) render as before, just ordered.
- [ ]**Step 1: Add a tree renderer** (replace `tableRow` helper, lines 14-18)
- [ ]**Step 3: Smoke locally against prod data (read-only)**
Run the app pointed at prod read-only, or eyeball after deploy. Minimum: `node -e "require('./public/views/space.js')"` won't run (browser ESM) — instead verify via deploy in Task 3.
- [ ]**Step 4: Commit**
```bash
git add public/views/space.js
git commit -m "feat(space-view): render pages as ordered sectioned tree"
```
### Task 3: Deploy the code change
**Files:** none (deploy)
- [ ]**Step 1: Bump version** in `package.json` + `server.js` VERSION const + add a CHANGELOG entry (alpha-20).
Q -c "SELECT name FROM schema_migrations WHERE name='020_page_position.sql';"
```
Expected: health = `2.0.0-alpha.20`; `position` column present; migration row present. Open `void.hynesy.com` → a space → confirm pages render as a tree (still alphabetical until positions are set in Phase 2).
---
## Phase 2 — Wiki → traditional documentation area
Make `wiki` the ordered, sectioned source of truth, and remove Void-app dev docs that don't belong in a homelab wiki (they move to The Void in Phase 4/6).
### Task 4: Section the Wiki + set order
**Files:** none (SQL on prod)
- [ ]**Step 1: Move Void-app dev docs OUT of `wiki` into `void` (The Void)**
These 6 "Void 2.0 — *" pages + "Dashboard rebuild & Orthos overhaul" are project history, not homelab infra:
Expected: root → Start Here(Overview, Network map, Master Index) → Hosts & Services(...) → Operations(...). Open `void.hynesy.com` → Wiki space → confirm **Overview is at the top**, grouped under sections. This resolves the user's "out of order" complaint.
---
## Phase 3 — Dedup void1 ↔ wiki
Per the verdict table. Merges (content edits) go through the **web page editor** (regenerates html/embedding); structural drops via SQL.
### Task 5: Salvage divergent facts, then drop void1 duplicates
Open the **wiki** "Ollama LXC (102)" page in the Void editor. Reconcile against the void1 copy using these authoritative facts (void1's are newer; cross-checked vs memory `reference-ollama-ct102`):
- Binary path: **`/usr/share/ollama`** for models; service user **`ollama`** (not root); installed via the community-script then upgraded. (Resolve the `/usr/bin` vs `/usr/local/bin` conflict by verifying live: `pct exec 102 -- which ollama` — use the real path; do not leave both.)
- Keep wiki-only content: the **PATH gotcha**, the **keep-alive / multi-model tuning after the 62 GiB RAM upgrade**, and the **driver 595.58.03** detail.
- Keep void1-only content: the **"CRITICAL: preserving config across upgrades"** section (systemd drop-in for `0.0.0.0:11434` binding) — this is the most important salvage; verify it's present in the merged page.
- Add a one-line lineage note at top: `> Consolidated from the Void 1 and BookStack copies, 2026-06-05.`
Save. Confirm the page renders and a search for "preserving config" returns it.
For each, diff the void1 copy and append any **void1-only** lines that carry real facts into the wiki copy via the editor. Use this to see exactly what's void1-only:
```bash
diff <(QT -c "SELECT body_md FROM pages p JOIN spaces s ON s.id=p.space_id WHERE s.slug='void1' AND p.title='<VOID1 TITLE>'")\
<(QT -c "SELECT body_md FROM pages p JOIN spaces s ON s.id=p.space_id WHERE s.slug='wiki' AND p.title='<WIKI TITLE>'")
```
Title pairs: Operations notes↔Operations notes; Overview↔Overview; Network map↔Network map; "Gramps Web — CT 109 (2026-05-25)"↔"Gramps LXC (109)". Lines prefixed `<` are void1-only — judge each; most will be stale and can be skipped. Save each edited wiki page.
- [ ]**Step 3: Fold Homelab Topology into wiki Network map**
void1 "Homelab Topology" has no wiki twin but overlaps "Network map". Diff it against wiki Network map; salvage any unique device/IP rows into Network map, then it's covered by the void1 drop in Step 5.
- [ ]**Step 4: Verify nothing unique is about to be lost**
```sql
-- void1 pages that will be dropped, with their wiki survivor lengths for a final sanity glance
('Sacred Valley Widgets — Phase 4 Follow-up','done'),
('USB Auto-Sync Drive','idea'),
('VM 203 Docker Stack Rebuild','active'),
('Win10 → Mediastack Migration','idea'),
('Z2 → Cluster Migration','active'),
('iVentoy PXE Server','paused')
)ASm(name,st)
WHEREp.space_id=(SELECTidFROMv1)ANDp.name=m.name;
```
Expected: `UPDATE 10`.
- [ ]**Step 2: Salvage agent persona one-liners into the Agent Roster page, then delete the 7 agent "projects"**
The 7 agent-named projects (Dross, Eithan, Lindon, Little Blue, Mercy, Orthos, Yerin) are personas, not projects. Their descriptions are 1-liners. Append any not already on "Agent Roster & Personas" (now in The Void), then:
- [ ]**Step 1:** The wiki "Master Index" survived (wiki copy was fuller). Open it in the editor and update links so they point at the new sectioned Wiki structure + The Void hub; remove dead links to deleted void1 pages. Save.
---
## Phase 5 — Fold void3 into the Void 3.0 project
### Task 10: Move void3 pages into The Void under a Void 3.0 hub page, link to the project
**Files:** none (SQL on prod)
- [ ]**Step 1: Create a Void 3.0 hub page in The Void**
**User decision (2026-06-05): KEEP the plan pages** — give them a home in The Void (not the Wiki, since they are project artifacts not infra reference). Move them under an "Implementation Plans" hub page in `void` and link each to its related project.
### Task 11: Move plan pages into The Void under an "Implementation Plans" hub, then delete the empty plans space
'_Implementation plans for homelab + Void projects, migrated from the former plans space. Canonical copies also live in the repo `docs/superpowers/plans/` and `~/.claude/plans/`. Child pages below; each is linked to its related project._',3)
ONCONFLICT(space_id,slug)DONOTHING;
```
- [ ]**Step 2: Move all 6 plan pages under the hub**
(The two Farm plans — "Farm (won) Failure-Recovery Plan", "Farm Timelapse System — Implementation Plan" — have no matching project in The Void; they remain under the hub, unlinked. Optionally create Farm projects later.)
- [ ]**Step 4: Confirm plans space is empty, then delete it**
DELETEFROMconversationsWHEREspace_id=(SELECTidFROMp);-- drop the placeholder convo
DELETEFROMspacesWHEREslug='plans';
```
Expected: count `0`, then `DELETE 1`.
### Task 12: Decide `external-research`
**Files:** none
- [ ]**Step 1:**`external-research` is empty but is the bound Space for the MCP external-research agent (`reference-void-mcp-endpoint`). Check it's still in use:
- [ ]**Step 2:** If an agent is bound → **keep** the space (add a one-line description page explaining its purpose). If no agent → `DELETE FROM spaces WHERE slug='external-research';`.
---
## Phase 7 — Lineage cross-links
### Task 13: Express doc lineage between The Void projects and Wiki service docs
**Files:** none (SQL + web editor on prod)
- [ ]**Step 1: Mediastack lineage (the user's example)** — add an evolution note + link
In the editor, append to Wiki "Mediastack LXC (100)":
```
> **Lineage:** First documented under Void 1. Now CT 100 on Z, Donatello/Leonardo pools, syncoid daily replica Z→Z3, and the Void-2 ingress host. See The Void › Void 2.0.
```
Then link the Void 2.0 project → the Mediastack page:
- [ ]**Step 2: Repeat for the other materially-evolved services** — Ollama (GPU userspace driver + sharing), Cluster and HA (qdevice, replication). Same pattern: add a one-line lineage note in the Wiki page + an `entity_links` row from the relevant Void project.
---
## Phase 8 — Verify, re-embed, finalize
### Task 14: Final verification
**Files:** none
- [ ]**Step 1: Space inventory is the target shape**
Content edits made via the web editor already re-embed. For pages changed only by SQL (parent/position/space moves) embeddings are still valid (body unchanged). If any body was edited via SQL, run the app's embed backfill:
```bash
ssh root@192.168.1.216 'cd /opt/void-server && node lib/db/backfill_embeddings.js 2>/dev/null || echo "no backfill script — re-save the page in the editor"'
```
- [ ]**Step 4: UI walkthrough** — open `void.hynesy.com`:
- Wiki space: Overview at top, three sections in order, no Void-2 plan docs.
- The Void space: projects Void 1.x/2.0/3.0 + the 10 homelab projects with corrected statuses; Void 1.x retrospective with its historical children; Void 3.0 hub with the 8 audit pages; Build Log with its dev-doc children.
- Search "preserving config across upgrades" → returns the merged Ollama page.
- [ ]**Step 5: Update the project memory** — note the consolidation done (spaces 7→3, wiki sectioned, void1/void3/plans retired) in `void-v2-roadmap` / `void-v2-execution-in-progress`, since the roadmap's "clean up old void1/void3/plans spaces" item is now complete.
- [ ]**Step 1:** Leave BookStack content as-is (it's already Overview-first). Do **not** invest in re-chaptering. Optionally add one note to BookStack "Overview": `> Primary docs now live in The Void Wiki (void.hynesy.com). This BookStack is a secondary reference mirror.` Skip if not wanted.
- **Destructive steps** (Tasks 5,7,8,10,11) are each gated by a verification query proving a survivor exists before delete, and the whole run is recoverable from Task 0's snapshot + pg_dump.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.