# State **Currency is compared, not declared.** `verify.sh` warns unless this file's last commit is at least as new as the last commit touching `.go`, so it ships *inside* the change it describes — no sha to write, and no trailing commit to write one (ADR-0057). If this file disagrees with the code, the code is right and this file is a bug. ## Inventory The engine- and agent-facing docs live in `harness/`, not `docs/` (ADR-0082). `docs/` is reserved for documentation aimed at whoever uses khosra and does not exist yet — an end-user documentation site is planned, with its home and whether its claims are gated both undecided. Line counts are **not** here: `harness/surface.md` is generated from the code and carries per-file sizes plus every declaration's location (ADR-0053). This column drifted on six files before it was removed, which is what a number written in two places always does. What each file is *for* is the fact this table owns. | File | Purpose | |---|---| | `go.mod` | module `khosra`; `goldmark`, `x/text`, `yaml.v3` direct | | `internal/content/doc.go` | package comment | | `internal/content/content.go` | bundles: `os.Root` open, walk, frontmatter split, key/lang derivation, NFC, tag slugs, partial files, permalink building | | `internal/content/clock.go` | the one place the engine reads the wall clock, which `verify.sh` enforces by filename | | `internal/content/extras.go` | a bundle's supporting files: enumeration, classification, and their URLs (ADR-0047) | | `internal/content/settings.go` | `site.yaml`: the site's own declarations (`base`, `title`) and absolute-URL building (ADR-0039) | | `internal/content/site.go` | the indexed site: lookup with language fallback, aliases, `Query` and `Run`, sections, `Sequence`, `Everything`, slug routes, publication visibility | | `internal/render/theme.go` | parsing the theme: the embedded reference templates, a site's overlay of them, and the stylesheet. Split from `render.go` at the length advisory — parsing a theme runs once per rebuild, rendering with one runs per request | | `internal/render/render.go` | goldmark with the typographer, the render methods. A Renderer never changes after `New`: a rebuild builds a new one and it is swapped with the index as a single `web.Snapshot`, so no page is assembled from two of them (ADR-0055, ADR-0056, ADR-0077). Heading ids are a parser option set here, declared or derived (ADR-0058, ADR-0066), and this is the one renderer that enables raw HTML (ADR-0060). `Compose` is the seam a merging bundle's splice arrives through | | `internal/render/view.go` | the theme contract in Go, and now actually all of it: `Page` (with `Assets`, `Styles` and `Scripts` — the assets a page's own calls and `use:` asked for, ADR-0079), `List`, `Sequence`, `Extras`, `Item`, `Partial`, `Fragment` (with `Body`, `Headings` and `Lang` — ADR-0064, ADR-0065, ADR-0067), `Heading`, `Picture`, `Origin` | | `internal/render/chrome.go` | the engine's own words: phrase table, month names, digits, and the `t`/`num`/`day` template funcs (ADR-0034), including the words a shortcode fragment supplies when the author gives none (ADR-0067) | | `internal/render/templates/` | reference theme, complete (six icon names map to Unicode, no assets — ADR-0063): `base.html` (shell, navigation, language links, feed and OpenGraph), `page.html` (bundle, sequence, tags, extras), `list.html`, `extras.html`, `shortcodes/` — seven fragment files rather than one, and a site may use either form (ADR-0071) — with the `sizes` its own layout implies (ADR-0068), `theme.css` (ADR-0026, ADR-0049) | | `internal/ext/shortcodes/` | first feature: `::name{key=value}` block parser and node renderer, rendering through a theme fragment (ADR-0036). `figure`, `gallery`, `include`, plus the derivative pass and remembered picture inspection, bounded and least-recently-used in `memo.go` (ADR-0042, ADR-0044, ADR-0073). `FootnotePrefix` namespaces an included file's footnote ids (ADR-0058). Directive syntax since ADR-0059, plus `icons.go`: `:name:` inline, rendered by the theme's one `icon` fragment (ADR-0063), `containers.go`: `:::name{…}` … `:::` wrapping a rendered body (ADR-0064), `toc.go`: the document's headings for a `::toc` call, to a depth the call may set (ADR-0065, ADR-0066), and `code.go`: chroma highlighting, a fence's options, and snippets read from a file (ADR-0075). `Merge` splices includes before the parse for a bundle that asks for it (ADR-0066) | | `internal/ext/notation/` | the inline marks CommonMark lacks: `~sub~`, `^sup^`, `==mark==`, and `~~strike~~`, which it owns so a single tilde can mean subscript (ADR-0061). `abbr.go` adds `*[TERM]:` definitions and the pass that expands them (ADR-0062) | | `internal/ext/scaffold/` | writes one draft directory bundle into a site root through `os.Root`: never an overwrite | | `internal/ext/watch/` | polls `content/` and `templates/` on an interval it is given, ignores editor droppings, and reports a settled change (ADR-0022, ADR-0048, ADR-0056). `site.yaml` is deliberately not fingerprinted (ADR-0055) | | `internal/ext/links/` | eighth feature: relative Markdown links become the URLs they are served at, resolved through key → route so a `slug` rename cannot break one (ADR-0087). Rewrites only destinations naming a bundle; an absolute URL, a fragment, a `mailto:` and any non-`.md` relative path are left exactly as written | | `internal/ext/discover/` | seventh feature: `/robots.txt` and `/sitemap.xml`, absolute and only with a declared base (ADR-0039). Left core in ADR-0085 — exact paths somebody else's software asks for by name, owning no core concept | | `internal/ext/passthrough/` | fifth feature, and the first to own a **route** (ADR-0081): files in `root/` served at the exact path they occupy, `.tmpl` rendered as text with the site's own settings, headers declared per path in `root/_headers.yaml`, underscore-prefixed names not addressable | | `internal/ext/check/` | third feature: validates a site root — what the engine worked around, broken internal links, missing titles and alt text, mixed series ordering, and calls left in the retired shortcode form (ADR-0059) | | `cmd/khosra/wire.go` | the only list of enabled features (`extensions.md`) — `extenders()` for the ones goldmark composes and `routes()` for the ones owning a URL path (ADR-0081), the `theme` function that builds the renderer this build ships (ADR-0072), and the Markdown dialect with it — tables, footnotes, definition lists, strikethrough, task lists (ADR-0058, ADR-0078) | | `internal/web/resolve.go` | URL → (key, lang, page, tag, feed, extras) or a canonical redirect | | `internal/web/extras.go` | the extras route: listing, one entry selected, or `?raw` bytes, all behind the bundle lookup | | `internal/web/asset.go` | files inside a bundle's own directory, looked up through the owning bundle so visibility can only ever inherit (ADR-0024) | | `internal/web/feed.go` | Atom for the site, a section or a tag, from dated bundles via one Query (ADR-0043) | | `internal/web/logging.go` | the access log: one Info line per request with method, path, status, bytes and duration, wrapped around the finished handler by `cmd` so tests stay quiet. Duration comes from `content.Now`, since the clock lives in one file (ADR-0086) | | `internal/web/web.go` | handler: `Snapshot` pairs the index with the theme that was current with it (ADR-0077); `serve` dispatches by kind, `serveBundle` answers the commonest one; listings, `/static/`, `/derived/`, degrade on failure. Mounts the exact paths features own, skipping any the engine already answers — a duplicate pattern would panic (ADR-0081). Since ADR-0085 it reserves only `/`: `/robots.txt` and `/sitemap.xml` are a feature's, so a clash *between* features is `wire.go`'s to settle | | `cmd/khosra/main.go` | flags (including `-poll`, zero to stop watching, and `-log-level`/`-log-format` which configure the one logger before anything can use it — ADR-0086), wiring, startup, the derivative pass, and the one atomic swap a change goes through, theme and index together in `rebuilder` (ADR-0077). `main` dispatches subcommands, `runServe` assembles the server, `rebuilder` is used at startup and on every change alike | | `cmd/khosra/check.go` | the `check` subcommand: parse, print, exit code. What counts as a finding lives in the feature | | `cmd/khosra/new.go` | the `new` subcommand: arguments in either order, then the feature does the writing | | `*_test.go` | table-driven, one file per source file — `shortcodes` has one each for icons, containers and the contents list; symlink escape (content and static), canonical paths, language fallback, aliases, pagination, tags, sequences, chrome, typography, shortcode escaping, galleries, includes, partials, site settings, absolute URLs, robots, sitemap, slug routes, bundle assets, derivatives, feeds, 404, plus benchmarks for the render path and the checker, unpublished visibility, listing shapes, scaffolding, extras, change detection, what a page can reach, the root listing, and the example site end to end — that last one in `cmd/khosra`, beside the wiring it proves (ADR-0072) | `root/` in the site root is served at the URL root: `root/pubkey` answers `/pubkey`, a `.tmpl` suffix renders the file as text with the site's own settings and is dropped from the address, and `root/_headers.yaml` declares headers per exact path (ADR-0081). Paths the engine already answers are skipped and logged. Every request produces one log line, and levels mean one thing each: **error** is something the engine could not do, **warn** is something it worked around while still serving — all of ADR-0029's category — **info** is lifecycle and requests, **debug** is off by default (ADR-0086, `conventions.md`). `-log-level` and `-log-format` (text or json) configure it. A page carries only the CSS and JS its own shortcode calls or its `use:` list asked for, rendered once each from the theme's `assets:` fragments, plus its own `styles`/`scripts` files — bundle-relative, anything climbing out dropped (ADR-0079, ADR-0080). The reference theme emits the stylesheets and **no `