Files
oikos/plans/done/2026-07-06-adopt-wiki-hq-doc-architecture.md

11 KiB
Raw Blame History

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 by mcp/build_host_files.py; read/written by bin/homelab.
  • oikos/ — kernel code, oikos/cards/ (explain tool, 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.yaml doc_page fields — per-host pointer; consumed by bin/homelab (die("no doc_page recorded…") near bin/homelab:1288). Repoint to knowledge/wiki/....
  • oikos/gen-topology.py / oikos/gen_topology_lib.py — write infrastructure/topology.md and link oikos/cards/ to doc pages. Move topology.md under knowledge/wiki/infrastructure/ and update the output-path constant (oikos/gen-topology.py:3, :49, :195).
  • oikos/cards/ templates and oikos/drift.py docstring at oikos/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 ## Changelog stays (parsed by get_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: 13 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.

  1. 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.
  2. 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:51 references resolve or are updated.
  3. Narrative move into knowledge/wiki/. Move containers/, vms/, infrastructure/, host narratives; add knowledge/index.md, knowledge/log.md, knowledge/sources/. Same commit: update inventory.yaml doc_page fields, oikos/gen-topology.py output path, all internal links. Verify: link-check clean; CLI doc_page lookups work; gen-topology.py writes to the new path; MCP get_page/search_docs return moved pages.
  4. Runbooks → skills. Reshape runbooks/*.md into .agents/skills/<name>/SKILL.md (they already carry risk_class, inputs, verification frontmatter — near-compatible). Update runbook-path references. Verify: frontmatter parses; lifecycle transitions still map to oikos/ontology.yaml.
  5. Style + README pass. Apply the writing-style standard and README pattern across narrative pages; add log.md entries recording the restructure. Verify: docs-lint clean.

Verification (end to end)

  • Link integrity: markdown link checker (or rg over ]( 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's doc_page read against a moved page — no "no doc_page recorded" error.
  • Topology generation: run oikos/gen-topology.py — writes the new topology.md path; oikos/cards/ links point at moved pages.
  • Substrate untouched: mcp/build_host_files.py regenerates hosts/*.yaml identically; git diff shows no substrate churn.
  • Style lint: banned-vocabulary grep over knowledge/ returns no hits; every folder README.md matches 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.