Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Do not invoke `bones/scripts/rc-*.sh` directly.

- Rendering runs through the [Oliver](https://github.com/drawmeanelephant/oliver) binary: `oliver render --from markdown < file.md`, stdin → stdout body HTML, stderr = warnings. Discovery order is `RK_OLIVER_BIN` override, then `oliver` on `PATH`. The authoritative contract is `home/content/docs/oliver-contract.md`.
- `bash rotkeeper.sh preflight` is the single renderer health check (discovery, executability, live smoke render); `render` routes through the same check. The adapter (`rc-oliver-adapter.sh`) strips a leading YAML frontmatter block before invoking Oliver.
- Oliver has no stable release yet: `setup.sh` (and CI) installs download-first from upstream's rolling `builds` release (binary + published `sha256sums.txt`, verified checksum and `oliver --version` reporting exactly the pin) and falls back to a Zig 0.16 source build — in both paths it pins commit `06dd6403c505b4863a54c548c978e494b55eb759` (the `OLIVER_PIN` variable in `setup.sh` — move it deliberately, never implicitly; the 2026-08-21 bump from `9ad86a3` (`9ad86a3763b8bd2f227fd5da94be9fc8ea5fa5fc`) via `06dd640` landed wrap fix #115 (PR #116, `wrap` parseArgs); the same-day bump from `6edb520c` landed Phase 6 S1+S2+S3+S4+S5 (`oliver meta` #107, `wrap` #108, `render` links #109, `plan`+`manifest` #110); the 2026-08-15 bump from `c8a8e06` adopted the builds release plus the `--version` stdout fix and GFM footnote/backref fixes; the 2026-08-14 bump from `e314dbbe` added the XHTML output profile (`--to xhtml`, fail-closed on raw HTML with `error.RawHtmlNotXmlWellFormed`) plus audit fixes #55–#58; the 2026-08-13 bump from `22b3c779` added the Cooklang frontend, CK1–CK5). XHTML is opt-in per page (`render_profile: xhtml` frontmatter) or per site (`render_profile` in `bones/config/rotkeeper.yaml`, default `html`), and needs an XHTML theme wrapper variant like `bones/templates/theme-spooky-dark-xhtml.html`. GFM pipe tables (alignment colons, escaped pipes) are supported; task lists and footnotes are not part of CommonMark and render literally — keep content CommonMark-safe for those. Textile input is supported via `input_format: textile` in `bones/config/rotkeeper.yaml` or via `.textile` source files, which always render as Textile regardless of the config default. Cooklang input works the same way: `input_format: cooklang` or `.cook` source files, which always render as Cooklang. Recipes live under `home/content/recipes/`.
- Oliver has no stable release yet: `setup.sh` (and CI) installs download-first from upstream's rolling `builds` release (binary + published `sha256sums.txt`, verified checksum and `oliver --version` reporting exactly the pin) and falls back to a Zig 0.16 source build — in both paths it pins commit `3f05bacb188ab28ad797430c82d9ee20080c5ed6` (the `OLIVER_PIN` variable in `setup.sh` — move it deliberately, never implicitly; the 2026-08-27 bump from `8460f28` to `3f05bac` landed the v3 generic hook (#269, oliver #127); the same-day bump from `06dd640` to `8460f28` landed shared template contract v2 (#244, oliver PR #126); the 2026-08-21 bump from `9ad86a3` (`9ad86a3763b8bd2f227fd5da94be9fc8ea5fa5fc`) via `06dd640` landed wrap fix #115 (PR #116, `wrap` parseArgs); the same-day bump from `6edb520c` landed Phase 6 S1+S2+S3+S4+S5 (`oliver meta` #107, `wrap` #108, `render` links #109, `plan`+`manifest` #110); the 2026-08-15 bump from `c8a8e06` adopted the builds release plus the `--version` stdout fix and GFM footnote/backref fixes; the 2026-08-14 bump from `e314dbbe` added the XHTML output profile (`--to xhtml`, fail-closed on raw HTML with `error.RawHtmlNotXmlWellFormed`) plus audit fixes #55–#58; the 2026-08-13 bump from `22b3c779` added the Cooklang frontend, CK1–CK5). XHTML is opt-in per page (`render_profile: xhtml` frontmatter) or per site (`render_profile` in `bones/config/rotkeeper.yaml`, default `html`), and needs an XHTML theme wrapper variant like `bones/templates/theme-spooky-dark-xhtml.html`. GFM pipe tables (alignment colons, escaped pipes) are supported; task lists and footnotes are not part of CommonMark and render literally — keep content CommonMark-safe for those. Textile input is supported via `input_format: textile` in `bones/config/rotkeeper.yaml` or via `.textile` source files, which always render as Textile regardless of the config default. Cooklang input works the same way: `input_format: cooklang` or `.cook` source files, which always render as Cooklang. Recipes live under `home/content/recipes/`.

## The BHO model

Expand Down
57 changes: 32 additions & 25 deletions GEMINI.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

If you are a Gemini agent (or a specialized subagent spawned by Antigravity) working within this workspace, these are your core directives for modifying or assisting with the Rotkeeper project.

**Current Version:** `v0.5.0`
**Current Version:** `v0.8.0`

## Context

Expand All @@ -13,18 +13,15 @@ Rotkeeper is a terminal-driven flat-file system for compiling markdown "tombs" i
1. **Do not break the Bash Scripts**: The core of Rotkeeper is its `.sh` scripts. When editing them, always preserve the `set -euo pipefail` architecture, the `trap_err` / `cleanup` trap mechanics defined in `rc-utils.sh`, and the `main()` guard pattern.

2. **Respect the Subdirectories**:
- `home/content/` — Strictly for user markdown input. Write `.md` files here.
- `home/content/messages/` — Ingested content from decentralized payloads. Don't write here directly.
- `home/content/` — Strictly for user markdown input. Write `.md`, `.textile`, or `.cook` files here.
- `home/content/messages/` — Preserved payloads and messages. Don't write here directly.
- `home/assets/` — Static assets (CSS, images, JS). Copied to `output/assets/` during `assets`.
- `output/` — Strictly for generated HTML. Never edit files here manually; edit source markdown or templates instead.
- `bones/scripts/` — Where the system logic lives. All scripts source `rc-utils.sh` → `rc-env.sh`.
- `bones/config/` — System configuration. Don't edit `rotkeeper.yaml` directly unless needed.
- `bones/config/` — System configuration (`rotkeeper.yaml`, `version`, `dip-whitelist.txt`).
- `bones/templates/` — HTML templates used during render.
- `bones/archive/` — Pack archives (tomb tarballs).
- `bones/releases/` — Release distributions.
- `bones/ingested/` — Ingested archive vault.
- `bones/tmp/` — Temporary staging.
- `messages-from-my-friends/` — Decentralized inbox for `.tar.gz` payloads to be ingested.

3. **Use the Dispatcher**: Never invoke `bones/scripts/rc-*.sh` directly. Always run `./rotkeeper.sh <command>`. Use `./rotkeeper.sh help` to see available actions.

Expand All @@ -34,40 +31,50 @@ Rotkeeper is a terminal-driven flat-file system for compiling markdown "tombs" i

| Command | Purpose |
|---------|---------|
| `init` | Full workspace initialization (reseed + assets + render + scan) |
| `render` | Convert Markdown → HTML via Oliver |
| `init` | Full workspace initialization (paths + assets + render + scan) |
| `render` | Convert Markdown / Textile / Cooklang → HTML via Oliver |
| `pack` | Archive output as `.tar.gz` tomb & export `source_markdown` JSON (also: `--content`, `--self`) |
| `release` | Create `lite` and `full` distribution `.zip` files |
| `ingest` | Unpack `.tar.gz` from `messages-from-my-friends/` into content |
| `preflight` | Report Oliver renderer availability and compatibility |
| `release` | Package canonical framework distribution `.zip` |
| `scan` | Audit files against manifest |
| `verify` | Check asset SHA256 integrity |
| `assets` | Generate asset manifest and copy to output |
| `index` | Build HTML index of rendered output |
| `templates` | List available HTML templates |
| `book` | Aggregate docs into binders (`--all`, `--scriptbook-full`, `--docbook`, etc.) |
| `meta` | Extract frontmatter metadata from content |
| `cleanup` | Back up and prune `bones/` (⚠️ destructive) |
| `reseed` | Reconstruct files from archive or bound markdown |
| `autopsy` | Catalog script help and file-write behavior into reports |
| `glue` | Auto-generate navigation glue for unindexed content directories |
| `links` | Audit rendered HTML links and local asset references |
| `a11y` | Audit theme accessibility (contrast, focus states, legibility) |
| `showcase` | Generate showcase preview pages for every HTML template |
| `dip` | Audit documentation coverage via DIP |
| `book` | Aggregate docs into binders (`--docbook`, `--scriptbook-full`, etc.) |
| `status` | Display system state summary |
| `bump` | Explicit semver bump (--major/--minor/--patch/--to) + changelog + git commit |
| `test` | Dry-run all scripts + Bats tests |
| `test` | Multi-layout integration test harness matrix (alias: `smoke`) |

## Available Templates

Use in frontmatter as `template: <name>`:
Use in frontmatter as `template: <name>` (or select via `theme_registry` in `rotkeeper.yaml`):

- `rotkeeper-blog.html` — Blog-style layout
- `rotkeeper-doc.html` — Documentation with navigation
- `theme-dark.html` — Clean, flat dark theme layout
- `theme-spooky-dark.html` — Fira Sans/Fira Code journal-terminal theme (default)
- `theme-spooky-light.html` — Light reading variant of the Spooky theme
- `theme-spooky-dark-xhtml.html` — Strict XHTML variant of Spooky Dark
- `theme-dark.html` — Clean, flat dark theme layout
- `theme-light.html` — Academic parchment light theme
- `theme-brutal.html` — High-contrast monospaced brutalist layout
- `theme-kawaii.html` — Pastel playful theme
- `theme-overgrown.html` — Forest decay mossy aesthetic
- `theme-phosphor.html` — Amber phosphor CRT terminal aesthetic
- `theme-textpattern.html` — Classic editorial layout with site navigation
- `theme-necropolis.html` — Dedicated 404 Tomb-Not-Found theme
- `theme-daisy.html` — DaisyUI presentation layer prototype
- `theme-daisy-vanilla.html` — Zero-dependency twin of DaisyUI theme
- `rotkeeper-blog.html` — Blog-style layout
- `rotkeeper-doc.html` — Documentation with navigation

## Decentralized Content Pipeline
## Preserving Content

When generating content that should be preserved:
1. Write `.md` files with YAML frontmatter in `home/content/`.
2. Run `./rotkeeper.sh pack --content` to bundle into a `.tar.gz`.
3. The archive lands in `bones/archive/` and can be copied to another repo's `messages-from-my-friends/` for ingestion via `./rotkeeper.sh ingest`.
3. The archive lands in `bones/archive/`.

## Workflow Example: Building a New Feature

Expand Down
2 changes: 2 additions & 0 deletions bones/config/rotkeeper.yaml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
project: "Rotkeeper"
author: "draw me an elephant"
title: "Rotkeeper Config"
description: "Minimal valid config for rendering tests"
default_template: "theme-spooky-dark.html"
Expand Down
1 change: 1 addition & 0 deletions home/content/docs/bones/scripts/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ This folder contains the core shell scripts that run Rotkeeper's commands.

<!-- ROTKEEPER-GLUE-START -->
- [tests/](<tests/index.html>)
- [rc-a11y](<rc-a11y.html>)
- [rc-assets](<rc-assets.html>)
- [rc-autopsy](<rc-autopsy.html>)
- [rc-book](<rc-book.html>)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
title: "Index of template-golden"
template: "theme-spooky-dark.html"
rotkeeper_glued: true
---

# Index of template-golden

<!-- ROTKEEPER-GLUE-START -->
- [theme-brutal.golden](<theme-brutal.golden.html>)
- [theme-spooky-dark-xhtml.golden](<theme-spooky-dark-xhtml.golden.html>)
- [theme-spooky-dark.golden](<theme-spooky-dark.golden.html>)
<!-- ROTKEEPER-GLUE-END -->
2 changes: 1 addition & 1 deletion home/content/docs/daisyui-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ tags:

# DaisyUI Primitive Map

This is the reference table for issue #249: which DaisyUI component or token implements each Rotkeeper UI primitive. Its consumers are the [DaisyUI prototype theme](#248) (`theme-daisy.html`) and the vanilla fallback that shares the exact same DOM (#250, `theme-daisy-vanilla.html`). The map records what the prototype does today, so the fallback (and any later theme) can target the same primitives with the same markup.
This is the reference table for issue #249: which DaisyUI component or token implements each Rotkeeper UI primitive. Its consumers are the [DaisyUI prototype theme](https://github.com/drawmeanelephant/rotkeeper/issues/248) (`theme-daisy.html`) and the vanilla fallback that shares the exact same DOM (#250, `theme-daisy-vanilla.html`). The map records what the prototype does today, so the fallback (and any later theme) can target the same primitives with the same markup.

The live proof is the [showcase page for the theme](../showcase/showcase-daisy.html) and its [zero-dependency twin](../showcase/showcase-daisy-vanilla.html) — the same scaffolded body every theme renders, through the DaisyUI presentation layer and through hand-written CSS respectively.

Expand Down
6 changes: 6 additions & 0 deletions home/content/docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ Sora prompt: “A glitching wiki carved into obsidian, with glowing CLI runes et
- [scripts/](<scripts/index.html>)
- [.agentignore](<.agentignore.html>)
- [.blessed](<.blessed.html>)
- [.editorconfig](<.editorconfig.html>)
- [.gitignore](<.gitignore.html>)
- [.shellcheckrc](<.shellcheckrc.html>)
- [AGENTS](<AGENTS.html>)
Expand All @@ -128,17 +129,22 @@ Sora prompt: “A glitching wiki carved into obsidian, with glowing CLI runes et
- [GEMINI](<GEMINI.html>)
- [README](<README.html>)
- [architecture](<architecture.html>)
- [creating-themes](<creating-themes.html>)
- [daisyui-map](<daisyui-map.html>)
- [dip-matrix](<dip-matrix.html>)
- [new-ritual](<new-ritual.html>)
- [oliver-contract](<oliver-contract.html>)
- [onboarding](<onboarding.html>)
- [patch](<patch.html>)
- [pre-commit](<pre-commit.html>)
- [publishing](<publishing.html>)
- [rotkeeper-reference](<rotkeeper-reference.html>)
- [rotkeeper-rituals](<rotkeeper-rituals.html>)
- [rotkeeper-schemas](<rotkeeper-schemas.html>)
- [rotkeeper](<rotkeeper.html>)
- [textile-guide](<textile-guide.html>)
- [textile-showcase](<textile-showcase.html>)
- [themes](<themes.html>)
- [workflow](<workflow.html>)
- [xhtml-profile](<xhtml-profile.html>)
<!-- ROTKEEPER-GLUE-END -->
2 changes: 1 addition & 1 deletion home/content/docs/oliver-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ oliver wrap --template bones/templates/theme-spooky-dark.html \

The extended tokens joined the dialect with the shared template contract v2 (rotkeeper #244, pin move `06dd640` → `8460f28`, oliver #126). `$version$` is not frontmatter — the adapter injects it from the canonical version source, the same single source `--version` and `@HELP` `{VERSION}` use. `$subtitle$`/`$tags$`/`$asset_meta$` are read from the source frontmatter by the adapter with `yq --front-matter extract` (see provenance below); `$warnings$` is reserved — no adapter feed exists yet, so it substitutes empty. Site **navigation** is delivered as raw HTML through a literal `<site-nav></site-nav>` placeholder (below), not an escaped token, because every non-literal `wrap` token html-escapes and a real nav is markup. The **v3 generic hook** (rotkeeper #269, pin move `8460f28` → `3f05bac`, oliver #127): the adapter merges every other scalar frontmatter key into `wrap_meta` (typed keys win the merge), so templates can reference any frontmatter field as `$field$` — `$page_type$` on the necropolis 404 theme is the first consumer. Bash keeps `TEMPLATE_DIR` boundary checks; Oliver handles interpolation when `wrap` is present.

## Extended metadata provenance (v2 + v3, implemented)
## Extended metadata provenance (v2 + v3, implemented) <a id="extended-metadata-provenance-v2-implemented"></a>

The extended tokens are live since the shared template contract v2 landed (rotkeeper #244): `oliver wrap` interpolates them on pins `8460f28`/`3f05bac` (oliver #126/#127, the latter adding the v3 generic hook), and the adapter feeds them into `wrap_meta`:

Expand Down
2 changes: 1 addition & 1 deletion home/content/docs/textile-guide.textile
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ Strikethrough uses a single hyphen pair: -like this-. Underline uses a plus pair

h2. Links

A link is "label":target. A title in parentheses after the label becomes the hover title. Parentheses in the URL itself clash with the title syntax and get eaten — keep link URLs parenthetical-free.
A link is @"label":target@. A title in parentheses after the label becomes the hover title. Parentheses in the URL itself clash with the title syntax and get eaten — keep link URLs parenthetical-free.

"Textile on Wikipedia":https://en.wikipedia.org/wiki/Textile is external. Bare URLs are links without ceremony: https://opencode.ai

Expand Down
4 changes: 2 additions & 2 deletions home/content/docs/workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ tags:

This guide walks the full Rotkeeper cycle from a cold checkout to a shipped framework zip. Every operation runs through the dispatcher: `bash rotkeeper.sh <command>` (or `./rotkeeper.sh`).

The cycle is: **preflight → init → author → render → verify → archive → release**, finished by the release-day checklist in section 8 below.
The cycle is: **preflight → init → author → render → verify → archive → release**, finished by the [release-day checklist](#8-release-day-checklist) in section 8 below.

## 1. Preflight — is the renderer ready?

Expand Down Expand Up @@ -86,7 +86,7 @@ Archives the rendered HTML and metadata into a versioned tarball under `bones/ar

`release` stages the repository against an explicit root-entry allowlist, excludes dev-only and forbidden trees (caches, logs, temp, output, credentials), generates `bones/config/release-manifest.txt` inside the archive, and fails fast on unexpected root entries, missing required files, or forbidden artifacts. The zip lands at `bones/archive/releases/rotkeeper-<VERSION>.zip`.

## 8. Release-day checklist
## 8. Release-day checklist <a id="8-release-day-checklist"></a>

Run the full loop before tagging a version — a release is only real when a clean environment reproduces the advertised workflow:

Expand Down
1 change: 1 addition & 0 deletions home/content/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,5 +87,6 @@ Sora prompt: "A decayed tombstone interface for Rotkeeper.com—ghostly monospac
- [recipes/](<recipes/index.html>)
- [rotkeeper/](<rotkeeper/index.html>)
- [showcase/](<showcase/index.html>)
- [404](<404.html>)
- [my-first-page](<my-first-page.html>)
<!-- ROTKEEPER-GLUE-END -->
11 changes: 11 additions & 0 deletions home/content/messages/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
title: "Index of messages"
template: "theme-spooky-dark.html"
rotkeeper_glued: true
---

# Index of messages

<!-- ROTKEEPER-GLUE-START -->
- [necromancer-notes-soul-audit](<necromancer-notes-soul-audit.html>)
<!-- ROTKEEPER-GLUE-END -->
22 changes: 22 additions & 0 deletions home/content/showcase/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,25 @@ Preview every theme through the same content. Each card links to its full showca
</div>

> Generated by `rotkeeper.sh showcase` — 15 themes. Run `bash rotkeeper.sh render` to refresh.

<!-- ROTKEEPER-GLUE-START -->
- [showcase-brutal-mac](<showcase-brutal-mac.html>)
- [showcase-brutal-pwsh](<showcase-brutal-pwsh.html>)
- [showcase-brutal-unix](<showcase-brutal-unix.html>)
- [showcase-brutal](<showcase-brutal.html>)
- [showcase-daisy-vanilla](<showcase-daisy-vanilla.html>)
- [showcase-daisy](<showcase-daisy.html>)
- [showcase-dark](<showcase-dark.html>)
- [showcase-kawaii](<showcase-kawaii.html>)
- [showcase-light](<showcase-light.html>)
- [showcase-necropolis](<showcase-necropolis.html>)
- [showcase-overgrown](<showcase-overgrown.html>)
- [showcase-phosphor](<showcase-phosphor.html>)
- [showcase-preview](<showcase-preview.html>)
- [showcase-rotkeeper-blog](<showcase-rotkeeper-blog.html>)
- [showcase-rotkeeper-doc](<showcase-rotkeeper-doc.html>)
- [showcase-spooky-dark-xhtml](<showcase-spooky-dark-xhtml.html>)
- [showcase-spooky-dark](<showcase-spooky-dark.html>)
- [showcase-spooky-light](<showcase-spooky-light.html>)
- [showcase-textpattern](<showcase-textpattern.html>)
<!-- ROTKEEPER-GLUE-END -->
Loading