11 KiB
2026-07-06 — Adopt the wiki-hq documentation architecture
Goal
Reorganize the Homelab-Docs narrative layer into the wiki-hq
(/Users/dtoro/Downloads/wiki-hq-main) documentation model — sources / wiki / index / log
plus an .agents/ separation and a single lint-checkable writing-style standard — without
breaking the Oikos machine-readable substrate that reads fixed paths. Keep the existing Mermaid
topology generator (no LikeC4).
Context
Homelab-Docs is already a mature operational-docs system: inventory.yaml as source of truth,
generated hosts/*.yaml, an MCP server, a homelab CLI, and the Oikos OODA kernel (scheduler,
drift, decide, ledger, approvals). Its weakness is on the narrative side — the prose layer grew
organically and lacks the discipline wiki-hq shows:
- No enforceable writing-style standard (CONTRIBUTING.md has a one-line "voice" note; CAVEMAN.md governs agent chat, not docs).
- Index/README files are inconsistent — some pure listings, some prose+tables, some with stale counts.
- No append-only operations log for doc maintenance — doc changes are visible only in git.
- Agent instructions and human content are interleaved at the repo root (AGENTS.md, OIKOS.md, CAVEMAN.md, CONTRIBUTING.md, GLOSSARY.md alongside
containers/,infrastructure/, …).
Decision (confirmed with operator): full structural adoption, keep Mermaid, adopt all four borrows — writing-style guide, section-index/README pattern, append-only per-area logs, and agent-instruction separation.
Hard constraint: protect the operational substrate
These paths are read programmatically and must not move (see mcp/server.py, bin/homelab, oikos/):
inventory.yaml(root) — MCP (mcp/server.py:36), CLI (bin/homelab:36), scheduler, drift, relations, gen-topology.hosts/*.yaml(root, generated) —HOSTS_DIR(mcp/server.py:37); written bymcp/build_host_files.py; read/written bybin/homelab.oikos/— kernel code,oikos/cards/(explaintool,mcp/server.py:38),oikos/state.json.secrets/,secrets-issuance/,ssh/,scripts/,tools/,vps/,bin/,bootstrap.sh.
Two MCP tools are path-agnostic and survive any narrative reorg: search_docs (ripgreps all
*.md) and get_page(path) (agent supplies a repo-relative path). The ## Changelog convention
must stay on node pages — get_changelog (mcp/server.py:214) and the ledger parse it. New
log.md files are additive, not a replacement for per-page changelogs.
Current → target structure
Restructure the narrative layer only; leave the substrate in place.
Homelab-Docs/
README.md # human landing page (kept; refreshed to new nav)
AGENTS.md # kept at root (conventional discovery path)
.agents/ # NEW — agent-facing instruction, separated from content
shared/
writing-style.md # NEW — adapted from wiki-hq (homelab voice)
llm-wiki.md # NEW — the sources/wiki/index/log contract for THIS repo
caveman.md # moved from CAVEMAN.md (agent chat mode)
page-templates.md # moved from CONTRIBUTING.md (page templates)
domains/
knowledge/schema.md # contract for the current-state wiki
operations/schema.md # contract for runbooks / investigations / plans
skills/ # runbooks reshaped as SKILL.md (Phase 4)
lifecycle-provision-node/SKILL.md
service-health-check/SKILL.md
...
OIKOS.md # operating-model doc (moved; agent-facing)
knowledge/ # durable current-state wiki (Feedback/authoritative layer)
index.md # pure listing → section indexes only
log.md # append-only doc-maintenance operations log
GLOSSARY.md # moved from root
sources/
index.md # flat catalog table
references/ # external docs (from infrastructure/references/)
wiki/
hosts/ README.md + hubris.md + strong.md
containers/ README.md (= today's index.md) + <id>-<name>.md
vms/ README.md + <id>-<name>.md
infrastructure/ README.md + grouped: network/ identity/ storage/ ingress/ operations/
operations/ # operator runbook narrative index
index.md commands.md agent-enrollment.md hermes-agent.md
investigations/ # incident evidence (Observe sources)
README.md + log.md + YYYY-MM-DD-*.md + archive/
plans/ # projects / design docs (Act)
README.md + YYYY-MM-DD-*.md + done/
# substrate — UNCHANGED (see Hard constraint)
inventory.yaml hosts/*.yaml oikos/ mcp/ secrets/ secrets-issuance/
ssh/ scripts/ tools/ vps/ bin/ bootstrap.sh
hosts/ split: generated hosts/*.yaml stay at root (substrate); only the two narrative pages
hosts/hubris.md and hosts/strong.md move to knowledge/wiki/hosts/. This is the one directory
where machine and narrative content currently mix.
Consumers to update when narrative paths move
Same phase as the move:
inventory.yamldoc_pagefields — per-host pointer; consumed bybin/homelab(die("no doc_page recorded…")nearbin/homelab:1288). Repoint toknowledge/wiki/....oikos/gen-topology.py/oikos/gen_topology_lib.py— writeinfrastructure/topology.mdand linkoikos/cards/to doc pages. Movetopology.mdunderknowledge/wiki/infrastructure/and update the output-path constant (oikos/gen-topology.py:3,:49,:195).oikos/cards/templates andoikos/drift.pydocstring atoikos/drift.py:218(containers/121-caddy.md) — cosmetic, update for accuracy.- Internal cross-links — repo-wide relative-link rewrite + link-check pass.
- Same-session update rule (
CONTRIBUTING.md:125) — rewrite its path checklist to the new layout.
search_docs, get_page, get_changelog need no code change.
Writing-style standard (adapted, not copied)
Create .agents/shared/writing-style.md from
/Users/dtoro/Downloads/wiki-hq-main/.agents/shared/writing-style/writing-style.md:
- Keep: banned-vocabulary list (puffers, "leverage/utilize/delve", poetic nouns, promotional adjectives), information-density rule, bold-leading-phrase pattern, tables-over-bullets,
>blockquotes for caveats, one-sided cross-references, "cross-references are content not catalog". - Adjust voice: wiki-hq mandates strict third-person "no you". Homelab docs are operator runbooks that already use imperative recipes. Allow imperative/second-person in runbooks, recipes, and skills; third-person reference voice for node/infrastructure descriptions. State this exception explicitly.
- Clarify vs CAVEMAN.md: Caveman governs agent chat responses; writing-style governs committed docs. No conflict.
- Make it lint-checkable: the Oikos lint surface (or a new
.agents/skills/docs-lint) greps banned words + structural violations.
Reconciling "append-only per-area logs" with the Oikos ledger
- The Oikos change ledger (
oikos/ledger.py) stays authoritative for infrastructure changes (who/what/risk/approval/verification). Do not duplicate it. - Per-page
## Changelogstays (parsed byget_changelog). - New per-area
log.md(knowledge/log.md,investigations/log.md,plans/log.md) records doc-maintenance operations only — restructures, source ingests, lint sweeps — in wiki-hq's single-line format## [YYYY-MM-DD] <op> | <summary>.
Convention: plans always live in plans/
The restructure must codify — in .agents/domains/operations/schema.md, AGENTS.md, and
.agents/shared/page-templates.md — that any plan or design doc for the Homelab is always
written into the repo plans/ folder (plans/YYYY-MM-DD-slug.md), never into a scratch/agent
plan path, an ad-hoc location, or a chat message. Agents drafting a plan create the file under
plans/, list it in plans/index.md, and move it to plans/done/ on completion. This rule is
stated once in the operations schema and cross-referenced from AGENTS.md so every agent sees it
at orientation.
Section-index / README pattern
Every folder gets a README.md: 1–3 sentence prose intro, then a single two-column nav table
| Document | What it covers |, nothing else — no stale counts, no duplicated prose. Pure-listing
index.md files (e.g. containers/index.md) become the folder README.md. Root README.md stays
the human landing page (may exceed the strict pattern).
Phased rollout
Each phase independently valuable, independently verifiable, committed separately.
- Conventions first (no moves). Add
.agents/shared/writing-style.md,llm-wiki.md; move CAVEMAN.md →.agents/shared/caveman.md, CONTRIBUTING.md →.agents/shared/page-templates.md(leave thin root stubs pointing to the new locations). Verify: links resolve; MCP untouched. - Agent-instruction separation. Move OIKOS.md →
.agents/OIKOS.md; author.agents/domains/{knowledge,operations}/schema.md. Keep AGENTS.md at root, pointing at.agents/. Verify: AGENTS.md still the discovery entry;tools/setup-hermes-soul.sh:51references resolve or are updated. - Narrative move into
knowledge/wiki/. Movecontainers/,vms/,infrastructure/, host narratives; addknowledge/index.md,knowledge/log.md,knowledge/sources/. Same commit: updateinventory.yamldoc_pagefields,oikos/gen-topology.pyoutput path, all internal links. Verify: link-check clean; CLIdoc_pagelookups work;gen-topology.pywrites to the new path; MCPget_page/search_docsreturn moved pages. - Runbooks → skills. Reshape
runbooks/*.mdinto.agents/skills/<name>/SKILL.md(they already carryrisk_class,inputs,verificationfrontmatter — near-compatible). Update runbook-path references. Verify: frontmatter parses; lifecycle transitions still map tooikos/ontology.yaml. - Style + README pass. Apply the writing-style standard and README pattern across narrative pages; add
log.mdentries recording the restructure. Verify: docs-lint clean.
Verification (end to end)
- Link integrity: markdown link checker (or
rgover](targets) after each move phase; zero broken relative links. - MCP resolves docs:
HOMELAB_CONTEXT_DIR=<repo>—get_page("knowledge/wiki/containers/104-gitea.md")returns content;search_docs("gitea")hits new paths;get_changelog(<moved page>)parses. - CLI doc_page lookups: exercise
bin/homelab'sdoc_pageread against a moved page — no "no doc_page recorded" error. - Topology generation: run
oikos/gen-topology.py— writes the newtopology.mdpath;oikos/cards/links point at moved pages. - Substrate untouched:
mcp/build_host_files.pyregenerateshosts/*.yamlidentically;git diffshows no substrate churn. - Style lint: banned-vocabulary grep over
knowledge/returns no hits; every folderREADME.mdmatches the intro-plus-nav-table shape.
Post-migration
Update plans/index.md to list this plan; on completion move it to plans/done/. Record the
restructure in the new knowledge/log.md. Update README.md and AGENTS.md navigation to the new
layout.