Files
khosra/docs/roadmap.md
T
bdeshi 39dcb8cc34 harness: soften two gates that would have taught --no-verify
The test-coupling gate failed comment-only and gofmt-only .go diffs, which
ship no behaviour and owe no test. Bypassing it would have cost every gate at
once, so it now compares added and removed lines with comments, blanks and
whitespace runs stripped: equal sets mean nothing happened. A new .go file is
never exempt.

The exported-doc-comment check is now a warning. No gate can tell
"// Load loads." from a useful sentence, so as a hard failure its cheapest
satisfaction was exactly the noise conventions.md calls worse than nothing.
Package comments and ADR citations in code stay hard.

Also fills in state.md's verified-against line and drops a stray blank line
left in roadmap.md by an earlier gate test.
2026-08-01 02:23:34 +06:00

4.2 KiB

Roadmap

Arcs, not sprints. An arc ends when its earn-triggers have fired, not on a date. Nothing from a later arc gets built early "since we are in the file anyway."

Arc 1 — the spine

  • HTTP server, one binary, no cache.
  • Bundle with language variants and fallback (ADR-0004).
  • Permalinks per ADR-0008, including aliases and permanent redirects.
  • Language routing per ADR-0009: English at root, /bn/ prefix, /en/… redirects to root.
  • Path traversal guard before anything faces the internet. The target is a self-hosted container (ADR-0010), so "not yet internet-facing" expires at the first deploy.

Done when: a URL reliably maps to a bundle, in two languages, with URLs you are willing to promise are permanent.

Arc 2 — earn the primitives at first real use

In this order, each at its trigger, never before:

  1. Query — at the first collection page (section index, latest posts).
  2. Stage pipeline — when the transform counter is due.
  3. View layer — per-bundle override; the data contract is already frozen by then (ADR-0023).

Done when: the View layer lands. The core stops growing here. Everything after is composition; core growth past this point means the plan was wrong. Record the core number verify.sh prints on freeze day in the retro line — from then on it is the figure that must not move.

Arc 3 — the networked layer

  • Feeds, JSON-LD, sitemaps, microformats — all Query + Stage + Effect.
  • Interaction primitive: comments, with the ADR-0003 trust boundary.
  • A thin internal ContentAPI, introduced with the comment write path — not before.
  • Access control as exactly one permission check, in one place.

Done when: an external party can react to a page without touching the content graph.

Arc 4 — pure composition

IndieWeb adapters (Micropub first — it buys an existing editor ecosystem for free), then ActivityPub only if still wanted, then delight: backlinks, transclusion, page-as-program, revision-as-craft. Optional admin panel here, as a second client over the ContentAPI.

Cross-cutting — when actually needed

Cache (when requests feel slow) — in-process first; Redis only once a second process must share it, and never as the only copy of anything (ADR-0010). Containerisation: one Dockerfile, one binary, no orchestration until a second service exists, and the site root is a mounted volume rather than baked in (ADR-0022). Updating that volume is the host's job; the engine only notices. Admin/editor deferred — git already works, and Micropub may remove the need entirely.

Admin/editor position

Reframed as a second client over the thin internal ContentAPI. If built: a Markdown editor with live preview, not WYSIWYG. Better: a Micropub endpoint, which buys an ecosystem of existing editor apps and requires no UI. Likely optional forever, given git.

Closing an arc

Earn-triggers fired, /invariants run and clean, latent list triaged (fixed, scheduled, or accepted with a reason), retro line written in state.md.

Governors

  • No abstraction before its second concrete use; the counters in state.md decide, not intuition.
  • Own the data; borrow only infrastructure you can walk away from. Test: if this vanishes, do I lose data or just convenience?
  • Every feature is a leaf (architecture.md invariant 7). Trunks wait for a human decision.
  • Typography split: smart quotes, dashes, ellipses, widow prevention = server-side markup-aware Stage after Markdown parse, skipping code spans. Glyph shaping = the browser's job. Ligatures, text-balance, variable fonts = CSS.

Bengali and context specifics

Unicode slugs, NFC-normalised at every identifier boundary with hand overrides for terms and sections (ADR-0015). Bengali numerals and relative dates are a cheap Stage (২ ঘণ্টা আগে) applied to chrome — UI strings and server-pulled dynamic fragments — never to authored body text, which stays as written. Bengali tokenisation for search is the genuinely novel problem here — solve it well and deliberately, not as a side effect of adding search. The low-bandwidth, low-carbon ethos is coherent with Gemini output, PWA offline, and no-JS defaults; let that coherence break ties when two designs are otherwise equal.