Browse Docs pages
This page documents the exact fields of Rotkeeper's machine-readable files. It is derived from the scripts that read and write them (rc-assets.sh, rc-release.sh, rc-status.sh, rc-env.sh, rc-new.sh, rc-glue.sh); when a script and this page disagree, the script is authoritative.
bones/asset-manifest.yaml
Generated by bash rotkeeper.sh assets (rc-assets.sh). The previous manifest is archived to bones/archive/asset-manifest-<YYYY-MM-DD_HHMM>.yaml before regeneration. Empty asset trees produce a single # assets: [] comment.
- path: "css/theme-dark.css" # asset path relative to the layout's assets dir (home/assets in crypt)
sha256: "1dbb3b1b...c0b504d661" # hex digest via sha256sum or shasum -a 256 (shared rk_sha256)
| Field | Type | Rules |
|---|---|---|
path |
string | Relative to the assets dir; only [a-zA-Z0-9/._-] allowed, no .. or ../ segments, .DS_Store never listed |
sha256 |
string | Lowercase hex SHA-256 of the source asset file |
Lifecycle: written by assets and archived before rewriting. Render
warns when the workspace's asset manifest is absent; the render pass runs
asset synchronization. Assets prunes stale generated copies only from an
output tree marked generated. The asset manifest is separate from the
render/archive ledger bones/manifest.txt.
bones/config/rotkeeper.yaml
The only always-present configuration file; written by init, optional paths may be serialized there. Every other key has a fallback in the reader, so a minimal file (title + description + default_template) is valid.
title: "Rotkeeper Config"
description: "Minimal valid config for rendering tests"
default_template: "theme-spooky-dark.html"
layout_style: "crypt" # optional: crypt | busy | sterile
paths: # optional serialized path cache (init writes it)
CONTENT_DIR: "/path/to/rotkeeper/home/content"
TEMPLATE_DIR: "/path/to/rotkeeper/bones/templates"
| Field | Type | Read by | Default / fallback |
|---|---|---|---|
title |
string | status | β |
description |
string | status | β |
project |
string | status | [not set] |
author |
string | status, new, glue | [not set] / empty |
version |
string | status | [not set] (the authoritative version is bones/config/version) |
license |
string | status | [not set] |
default_template |
string | render, glue, new, bootstrap | theme-spooky-dark.html (legacy key; theme_registry.default wins over it) |
theme_registry |
map | render, glue, new, status | mode names β template files; default selects the site-wide theme (#252) |
input_format |
string | env, render, preflight, adapter | markdown; valid values markdown | textile | cooklang (anything else warns and falls back to markdown) |
render_profile |
string | env, render, adapter | html; xhtml requires a compatible wrapper and XML validation |
render_system_docs |
boolean | render | true; false excludes Docs, Help, and messages |
layout_style |
string | env | crypt; valid profiles crypt | busy | sterile |
paths |
map | env | derived per layout style when absent |
theme_registry semantics (#252): maps mode names to template files (e.g. daisy: "theme-daisy.html", daisy-vanilla: "theme-daisy-vanilla.html"). The default entry is the per-site theme and wins over the legacy default_template key; per-page template: frontmatter wins over both. rk_resolve_default_template (rc-utils.sh) validates registered values under the active layout's template directory and falls back to the first available template when the default is missing.
paths cache semantics: a serialized paths block is validated against the active layout and repository root on load (validate_layout_alignment in rc-utils.sh). init deliberately forces an environment reload after writing it; do not hand-edit a paths block without re-running init or the alignment check will report the mismatch.
bones/config/release-manifest.txt (in the release archive)
Generated inside the distribution by bash rotkeeper.sh release <version> (rc-release.sh). This is the bill of materials for a release; the legacy rotkeeper-bom.yaml no longer exists and never ships.
Rotkeeper framework distribution manifest
version: 0.5.2
model: framework distribution (dispatcher, bones system, templates, configuration, project docs)
ruleset: release allowlist v1 (explicit root entries, required spine, forbidden prefixes and artifacts)
listed_entries: <count>
entries:
rotkeeper/AGENTS.md
rotkeeper/bones/config/release-manifest.txt
...
| Field | Meaning |
|---|---|
version |
Release version from bones/config/version |
model |
Distribution model (framework distribution is the only supported model) |
ruleset |
Allowlist contract enforced against the archive |
listed_entries |
Number of files listed under entries: |
entries: |
One sorted, root-relative path per file inside the archive β the allowlist the packager verifies against |
Verification failures (unexpected root files, missing required spine, forbidden credentials/artifacts) abort the release before the archive is finalized.
bones/archive/ β tomb archives
pack writes timestamped .tar.gz tombs (tomb-<YYYY-MM-DD_HHMMSS>-NNNN.tar.gz), tombkit bundles (tombkit-*), content archives (tomb-content-*), and JSON exports (tomb-export-*). release writes the framework archive (releases/rotkeeper-<version>.zip).
Archive naming: a timestamp and random -NNNN tag reduce same-second
name collisions on GNU and BSD systems; this is not an enforced immutability
guarantee. Default and self archives embed metadata.json (name,
payload_sha256, payload_sha256_scope, timestamp, mode, and file count);
content-only archives do not. An embedded digest cannot cover the archive that
contains it, so payload_sha256 is the tar before metadata.json was
appended. Every mode records the final .tar.gz path and SHA-256 in
bones/manifest.txt; check the shipped archive against that ledger entry.
Pack verifies gzip -t.
Its failure trap removes an in-progress partial archive. Keep source exports
and full-system bundles private unless their contents are intended for sharing.
CLI --json output
Several dispatcher commands emit a single machine-readable JSON object on stdout when passed --json; human-facing output, report files, and exit codes are unchanged when the flag is absent. New outputs are tagged with a stable schema field (rotkeeper.<subject>.v1) so CI consumers can version-check before parsing. As everywhere else on this page, when a script and this page disagree, the script is authoritative.
scan --json
Emitted by bash rotkeeper.sh scan --json. Scan audits the render ledger (bones/manifest.txt): missing are ledger entries absent from disk, orphans are files under the rendered output tree the ledger does not list, and digests verify ledger-listed files. The report files under bones/reports/ keep their existing shape; this object carries the same findings inside an additive envelope. With or without --json, scan exits 3 whenever any counts value is nonzero, so CI can gate on the exit code and parse this object for detail.
{
"schema": "rotkeeper.scan.v2",
"generated_at": "2026-08-27T00:00:00Z",
"manifest": "bones/manifest.txt",
"counts": { "missing": 0, "orphans": 0, "digest_mismatches": 0 },
"missing": [],
"orphans": [],
"digest_count": 2,
"digests": {
"home/content/index.md": "1dbb3b1bβ¦c0b504d661"
},
"digest_mismatches": [
{ "path": "bones/archive/tomb-2026-08-27_120000-1234.tar.gz", "expected": "1dbb3b1bβ¦c0b504d661", "actual": "deadbeefβ¦00000000" }
]
}
| Field | Type | Rules |
|---|---|---|
schema |
string | Always rotkeeper.scan.v2 |
generated_at |
string | ISO-8601 UTC timestamp emitted at audit time |
manifest |
string | Manifest path audited, root-relative |
counts.missing, counts.orphans, counts.digest_mismatches |
number | Lengths of the arrays below, mirrored for convenience |
missing |
string[] | Ledger entries absent from disk; empty array when clean |
orphans |
string[] | Files under OUTPUT_DIR absent from the ledger; output/assets/ is exempt (owned by the assets ritual) |
digest_count |
number | Number of entries in digests |
digests |
map | Ledger-listed file path β lowercase hex SHA-256 (files present on disk only) |
digest_mismatches |
object[] | Ledger entries with a recorded SHA-256 (pack's <path> <sha256> two-space format) whose on-disk digest differs; each entry {path, expected, actual} where actual is hex or null when the file is absent (also in missing[]) |
v1 β v2: v1's full-tree walk never produced orphans/digests β the extension filter could not match under the script's IFS (#292). v2 scopes orphans to the output tree, retargets digests at ledger entries, and adds digest_mismatches[] verifying pack's recorded SHA-256 lines (P2).
dip --json
Emitted by bash rotkeeper.sh dip --json. Rows appear in matrix order
(sorted owned docs, then sorted unowned docs). --dry-run does not publish
docs or the matrix, but bootstrap logging and temporary JSON assembly still
write. The authored_guides array reports explicitly authored task guides
separately from core-target coverage.
With dip --dry-run --json, preview messages share stdout with the JSON
object. Extract the envelope before parsing:
bash rotkeeper.sh dip --dry-run --json | sed -n '/^{$/,/^}$/p' | jq .
{
"schema": "rotkeeper.dip-matrix.v1",
"generated_at": "2026-08-27T00:00:00Z",
"matrix_file": "home/content/docs/dip-matrix.md",
"totals": { "ok": 10, "stub": 0, "missing": 0, "stale": 0, "unowned": 0, "rows": 10 },
"rows": [
{ "target_file": "bones/scripts/rc-dip.sh", "doc": "bones/scripts/rc-dip.md", "last_code_edit": "2026-08-27", "last_doc_edit": "2026-08-27", "status": "OK" }
],
"ownership_collisions": [],
"obsolete_moved": [],
"degraded": { "autopsy_report": false, "fsbook_catalog": false }
}
| Field | Type | Rules |
|---|---|---|
schema |
string | Always rotkeeper.dip-matrix.v1 |
generated_at |
string | ISO-8601 UTC timestamp |
matrix_file |
string | Published matrix path relative to root |
totals |
map | Counts by core-reference status (ok, stub, missing, stale, unowned, exempt) plus total rows; placeholders and placeholder_pages include authored-guide findings |
rows[] |
object | target_file, doc, last_code_edit, last_doc_edit, status (all strings); targets without an owning script use "Unknown" |
authored_guides[] |
object | {doc, status, reviewed, placeholder_count}; repository-relative source path; status is Reviewed, Needs review, or Incomplete; no sidecar exemption is implied |
ownership_collisions[] |
object | {doc, claims} where claims lists the two generated sources claiming the same doc page |
obsolete_moved[] |
string[] | Docs moved to the obsolete tree this run (always empty under --dry-run) |
degraded.autopsy_report, degraded.fsbook_catalog |
boolean | True when that input artifact was missing and discovery degraded |
Other producers
status, links, and a11y each support --json today with command-specific shapes (see their reference pages). They predate the envelope convention above and do not carry a schema tag; treat their exact fields as defined by the scripts themselves.
Related
- Rendering contract β the template/input contract for rendering.
- Dispatcher reference β top-level CLI behavior.
- Help β task-based guides.
- Command reference