Skip to content

Latest commit

 

History

History
176 lines (140 loc) · 9.3 KB

File metadata and controls

176 lines (140 loc) · 9.3 KB

EmptyOS Documentation System

The structure of how EmptyOS documents itself — surfaces, audiences, what's authored vs generated, and a registry of every doc. This is the file to read (and update) when you change how the docs work. The reader-facing map lives in README.md; this file is the architecture behind it.

EmptyOS's principle is self-documenting (CLAUDE.md Principle 7): facts that drift are generated from the code, not hand-maintained. This doc encodes that rule so the docs can't quietly rot the way docs/APPS.md did (it sat at "70 apps" from April to June while the system grew past 110).


Four output surfaces

The same underlying facts render to four surfaces for four audiences. The factual parts of all four are fed by one shared extractorscripts/doc_data.py — so they can't disagree.

Surface What Where Generated by
Repo docs README, docs/*.md, CLAUDE.md the git repo authored + the generators below
Public site eos.binbian.net project/marketing site publish app → vault site source (30_Resources/EmptyOS-Site/) scripts/generate_emptyos_site.py
In-product docs eos app info <id>, /topology, /system capability inspector the running daemon live, from manifests + kernel state
Agent context .claude/rules/*, .agent-bus/, CLAUDE.md the repo, loaded into an AI's context authored

The public site is a renderer, not a separate tool: the same scan_apps() / scan_capabilities() / scan_release() that produce APPS.md and TIERS.md feed the site's app/capability/plugin pages. Fix a fact in the extractor → every surface picks it up.


Four audiences

Layer Question Primary docs
User / Visitor What is this? How do I run it? What can it do? README, GETTING-STARTED, APPS, live demo
App Builder How do I build an app / plugin / skill? APP-DEVELOPMENT, .claude/rules/*, eos app info, APP-SPECS
Operator / Deployer How do I deploy / package / configure? DEPLOYMENT, TIERS, AUTH, PRIVACY, RELEASING
Contributor / Agent How does it work? How do I evolve it? CLAUDE.md, DESIGN, SYSTEM-INTERNALS, .claude/rules/*, .agent-bus/

Two classification axes

Authored vs Generated — the load-bearing rule:

  • Generated (facts that drift) carry a <!-- auto-generated by … — do not hand-edit --> banner and a --check mode that fails CI when stale. APPS.md, TIERS.md, the capability/plugin tables on the site, and the root DESIGN.md design-token block.
  • Authored (judgment, philosophy, narrative, patterns) is hand-written: README, DESIGN, GETTING-STARTED, APP-DEVELOPMENT, every .claude/rules/*.

Shipped vs Internalrelease.toml [include] paths lists the docs that ship in a public git clone: README, CLAUDE.md, DESIGN, GETTING-STARTED, APP-DEVELOPMENT, APPS, TIERS. Everything else under docs/ is internal (design notes, audits, roadmaps).


Data flow

   code (manifests, capabilities/types.py, release.toml)
            │
            ▼
   scripts/doc_data.py          ← one deterministic extractor (no kernel boot)
        │   │   │
        │   │   └────────────► scripts/generate_tiers_doc.py → docs/TIERS.md
        │   └────────────────► scripts/generate_apps_doc.py  → docs/APPS.md
        └────────────────────► scripts/generate_emptyos_site.py → eos.binbian.net pages
                                     ▲
   scripts/doc_llm.py ───────────────┘   (best-effort, cached LLM prose polish; --llm)

doc_llm.py adds crisp one-line app summaries via the daemon's /assistant/api/chat (one-shot, context:false, Bearer token), cached by manifest hash in docs/doc-summaries.json (tracked) so unchanged apps never re-call. It is enrichment, never a dependency — every generator produces accurate output with no daemon, using the manifest description as the baseline summary.


Generators & commands

Script Produces Refresh Check (CI)
scripts/doc_data.py (shared extractor — no output) --dump / --json
scripts/doc_llm.py docs/doc-summaries.json (tracked) cache (called with --llm)
scripts/generate_apps_doc.py docs/APPS.md python scripts/generate_apps_doc.py [--llm] [--public-only] --check
scripts/generate_tiers_doc.py docs/TIERS.md python scripts/generate_tiers_doc.py --check
scripts/generate_emptyos_site.py site pages in the vault (incl. one per-app page apps/<id>.md per public app) python scripts/generate_emptyos_site.py --dry-run
scripts/gen-design-md.py root DESIGN.md token block python scripts/gen-design-md.py --check

The committed docs/APPS.md is comprehensive (public + extension tracks) for contributors. release-public.py regenerates it with --public-only in the snapshot (after the tier filter), so a public clone's catalog lists only the apps that actually ship (core + standard) — no references to extension/labs apps absent from the bundle. APPS.md intentionally omits per-app route counts: those recompute from @web_route on every code edit and would churn the doc (and the gate) on unrelated changes. Route totals live in the site/eos app list instead.

The --check modes are wired into scripts/preflight.py (scope docs) and the release path, so doc drift fails loudly — same pattern as the check-*.py scanners (.claude/rules/self-audit-loops.md).


Doc registry

Generated (do not hand-edit):

Doc Surface Owner script Shipped
docs/APPS.md repo generate_apps_doc.py yes
docs/TIERS.md repo generate_tiers_doc.py yes
DESIGN.md (root) repo gen-design-md.py (token contract)
site apps/plugins/capabilities.md public site generate_emptyos_site.py n/a
site apps/<id>.md (per-app intro, public version only) public site generate_emptyos_site.py n/a

Authored — primary (shipped):

Doc Audience Purpose
README.md User Front door — what/why/quick-start/architecture
docs/GETTING-STARTED.md User Install, configure, first boot
docs/APP-DEVELOPMENT.md Builder Build an app (pattern, manifest, UI)
docs/DESIGN.md Contributor Architecture, philosophy, consciousness model
CLAUDE.md Contributor / Agent Conversation-mode boot prompt (full architecture)

Authored — internal reference (current):

Doc Audience Purpose
docs/DEPLOYMENT.md Operator 5 deployment lanes; Hetzner + Caddy walkthrough
docs/RELEASING.md Operator Release flow + tier packaging
docs/AUTH.md Operator Single-user auth pin + rationale
docs/PRIVACY.md Operator Cloud-consent + vault-stays-local contract
docs/CONVERSATION-STACK.md Builder 5 chat backends × 8 frontends decision map
docs/CONTEXT-PACKING.md Builder Token-compression domain
docs/SYSTEM-INTERNALS.md Contributor Kernel boot, loaders, event bus internals
docs/APP-SPECS.md Builder Per-app spec sheets
docs/EOS-MARKDOWN-PROFILE.md Builder Vault Markdown storage + rendering contract
docs/SOFT-SCHEMA.md Builder VaultModel soft-typed frontmatter
docs/FRONTEND-DESIGN-LANGUAGE.md Builder Visual + interaction DNA (read before touching a page)
docs/ENGINEERING-APP-WORKFLOW.md Builder Algorithm-doc → KB → engine → calculator pipeline
docs/ROOMS-V3.md Builder Multi-participant rooms + review gate
docs/DOGFOOD-AGENT.md, docs/fix-agent.md Contributor Self-test/fix loop internals
docs/app-builder.md Builder In-app app generation
.claude/rules/* Agent ~45 pattern rules loaded into AI context
.agent-bus/ Agent Canonical store rippled to CLAUDE/GEMINI/AGENTS boot files

Authored — point-in-time (historical; not current reference): docs/BACKLOG.md, docs/MIGRATION.md, docs/HOME-COMPANION-REDESIGN.md, docs/EMPTYOS-EM-ROADMAP.md, docs/OPEN-SOURCE-BORROWING-PLAN.md, docs/KB-APP-ALIGNMENT-AUDIT.md, docs/EXPORT-ANALYSIS.md, docs/AGENT-BENCH.md, docs/AGENT-TEAM-PATTERNS.md, docs/CABLE-REPORT-LIMITS.md, docs/cable-rating-em-engine-integration.md, docs/ENGINEERING-WORK-LOOP.md, docs/legacy/. These captured a moment (a redesign, an audit, a plan). Keep for history; don't treat as the current state — verify against code.


Maintenance rules

  1. A fact that drifts → generate it. If you find yourself hand-editing a count, a capability list, an app table, or a tier roster, that belongs in doc_data.py + a generator, not in prose.
  2. Add a new doc → register it here (and add a line to README.md). State its audience, authored/generated, and shipped/internal.
  3. Promote a doc to shipped → add it to release.toml [include] paths and mark it shipped here.
  4. Author prose once. Philosophy/narrative lives in DESIGN/CLAUDE; don't restate it in generated docs — link instead.
  5. Run the gate. python scripts/preflight.py --scope docs before a release; it runs every generator's --check.