-
-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
Thirteen crates, layered so that the parts which must be provably correct have no I/O to be wrong about.
berrywiki-cli ──── berrywiki-import
│ (pure; foreign notebooks in)
┌──────────────┴───────────────┐
berrywiki-serve berrywiki-sync
(+ -render, -draft) │
│ └── berrywiki-a11y berrywiki-git
│ (audits the output) │
└──────────┬───────────────────┘
berrywiki-store ── berrywiki-appstate
│ (out-of-clone state)
berrywiki-core
(no I/O; the rules)
| Layer | Rebuildable? |
|---|---|
Markdown files in .wiki.git
|
No — this is the data. |
_Sidebar.md |
Yes, deterministically. |
| Page graph, backlinks, diagnostics | Yes, from the files alone. |
| Drafts, journal, search index | Yes; losing it costs at most unsaved drafts. |
berrywiki-core holds every rule and touches no filesystem: metadata
parsing and serialisation, heading and link extraction, hierarchy, backlinks,
diagnostics, sidebar generation. Because it has no I/O, all of that is testable
in-process.
berrywiki-store is the only layer that writes wiki content. Writes are
atomic — a temp file renamed into place, so no reader ever sees half a page.
Paths are validated component-wise against traversal and against names that
break Windows checkouts. A move writes and verifies the new file before
removing the old, so a crash leaves both files — a visible duplicate-id
diagnostic — never neither.
berrywiki-appstate and berrywiki-draft keep BerryWiki's own state
under the XDG state home, outside the clone.
berrywiki-git wraps a deliberately closed set of git operations. No
force-push, no reset --hard, no blanket working-tree discard, and fetch
before push. berrywiki-sync turns each completed store mutation into one
atomic logical commit. berrywiki-github mirrors a .wiki.git working
copy, read-only.
berrywiki-git-compat is not a feature — it is evidence. It reproduces
remote-change, non-fast-forward and merge-conflict situations and asserts that
no data is lost, so the safety claims above are tested rather than asserted.
berrywiki-render converts Markdown to HTML with comrak, escaping raw HTML
and neutralising dangerous URL schemes. berrywiki-serve is the three-pane
explorer and editor, with no third-party dependencies at all: a hand-rolled
blocking std::net server, no async runtime, no web framework.
berrywiki-a11y is a structural accessibility audit over a rendered page,
with no dependencies. It answers the only part of accessibility a program can
answer by itself: whether the structure a screen reader and a keyboard depend
on is present — a missing lang, an unlabelled control, a link with no text, a
heading level that jumps, a skip link pointing at nothing. It cannot tell you
whether the reading order makes sense, and nothing here should be read as
evidence that BerryWiki has been tested with a screen reader; it has not.
Colour contrast is deliberately out of scope and is recorded by hand in
ADR-0012 instead. It is a crate rather than a test helper because
berrywiki-serve sweeps its routes from an integration test as well as a unit
test, and an integration test cannot see a #[cfg(test)] item in src/.
berrywiki-import reads a foreign notebook into BerryWiki, and it is
pure: it opens no file, writes no file and holds no store. It takes the bytes
of a notebook and returns a model, which the CLI either prints as a dry run or
applies — so a dry run and a real import compute exactly the same value.
CherryTree .ctd XML is read; .ctb, .ctz and .ctx are refused by name
rather than half-handled, because reading them means a SQLite or 7-zip reader
and the workspace deliberately has one third-party crate. ADR-0015 rules how
that line is held: hand-roll plain-text formats, and shell out to a binary the
user already has only behind an explicit flag, never silently.
-
No JavaScript or TypeScript, hand-written or generated. Whether
generated client script may ever ship was ruled in ADR-0007 (2026-09-03):
it may, but only with a checked-in manifest recording each artefact's
sources, pinned toolchain, reproduced hash and permitted routes. Nothing
shipped changed on that day. The no-
<script>test stays in place byte-for-byte until a first generated artefact lands, and that manifest gate must exist before it may be relaxed. - No async runtime and no web framework in the server. It is a single-user localhost tool; the HTTP surface is the seam to swap later if that changes.
- No database. The file tree is the database.
Design reasoning lives in docs/decisions/ as ADRs, indexed on
Decisions. Package-by-package state
is in docs/execution/work-packages.adoc, and known debt — including the
absence of the proofs the project intends to have — is in
docs/execution/debt-register.adoc.