Files
bdeshiandClaude Opus 5 b313b729d9 review 130 feature ideas, and delete the lists that held them
One idea at a time: definition, necessity, priority, layer, recommendation. Every
row is now shipped, scheduled, parked with a trigger, or dropped with a reason —
so both tracking files are gone rather than left as a parallel backlog.

Roughly a third already shipped. A quarter needed only a theme fragment or CSS,
including several the list assumed were features: arbitrary `theme.*` frontmatter
attributes already reach templates through Extra (verified), native lazy loading
already ships and is deliberately absent on lead figures, and in-page timelines
are a theme-defined container.

roadmap.md gains an "Order of work" — nine bodies of work in sequence, because the
sections this review added had accumulated without one. Item 0 is a decision, not
work: core sits at ~2965 of 3000 and logging alone wants the remainder, so
discover.go moves out *and* the ceiling rises with an ADR. feed.go and
web/extras.go cannot move; they are resolver cases, and three parked items now
wait on that same seam decision.

Two ADRs came out of it.

ADR-0083: the dependency rule described a practice it forbade. "Stdlib first,
always" and "usually 40 lines of stdlib" would, read literally, have argued
against all five modules here — every one is a format or algorithm somebody else
specified, and their allowlist comments say so. Surfaced when this agent proposed
hand-rolling Reed–Solomon for QR encoding. The test is now whether you can verify
it, not whether you can write it, with compute-versus-hold as the counterweight.
conventions.md and allowed-deps.txt contradicted it and were realigned.

ADR-0084: the Effect primitive said every Effect is "idempotent and re-runnable
from scratch" — true of derivatives, false of anything outbound, since a sent
message cannot be recalled. Split into artifact-producing and outbound, the latter
idempotent only against a delivery ledger, at-least-once with a dedupe key, and
ledgers in a -state directory distinct from the disposable cache. Asked for as
forward-looking design so webmentions need no redesign; recorded as a shape rather
than built, the way extensions.md records the Extension struct. Also fixed a
STATUS claiming Effects were "not buildable yet" when the derivative pass has
inhabited them since ADR-0042.

Findings that were defects rather than ideas: the Atom feed emits no <author>,
which RFC 4287 requires. HTML comments in content are published verbatim —
verified — so anything commented out is already public, and a check warning is
scheduled rather than the engine deleting authored bytes. `Page` has no Date, so a
theme cannot mark up dt-published or show an article's own date.

A frontmatter naming rule after this agent proposed `archive` alongside the
accepted `archived`: no near-homograph keys, and name the benefit rather than the
vendor.

reference/microformats-and-indieweb.md is new and is the reference asked for —
microformats2 properties and IndieWeb rel values mapped to where a theme puts
them, with spec URLs, marked scheduled. rel="me" is the highest-value lowest-cost
item in that space and needs no endpoint at all.

Four things this agent got wrong and the human caught: asserting "the engine never
fetches" from a sentence scoped to the content repo, twice; inventing a
data-sovereignty argument for an item he had filed as "a cool geeky thing", when
the raw Markdown in his git already is the sovereignty; the archive naming; and
claiming microformats could be fully implemented today.

15 files, +556/-385. No code changed. Nothing was scheduled that this agent could
not name a consumer for.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-03 16:14:52 +06:00

15 KiB
Raw Permalink Blame History

Exploration catalog

Status: catalog — the verdicts are inside, one row each

Possible futures. Nothing here is committed. Presence in this list is not permission to build.

= highest fit-to-effort for this project's identity and values.

The leaf/trunk test — apply before any of this gets built

Definitions: architecture.md invariant 7. Leaf → buildable when wanted. Trunk → waits for an explicit human decision, in an ADR, on purpose.

Known trunks: ActivityPub, IPFS, Solid, hosted annotation servers, CRDT-backed editing. Sovereignty test for any of them: if this vanishes, do I lose data, or only convenience?

Use /leaf <topic> to get a verdict written into this file.

Verdicts

The human's 130-item feature list was reviewed one item at a time on 2026-08-02 and the file holding it is gone: everything is now either shipped, scheduled in harness/roadmap.md, parked below, or dropped below. Roughly a third already shipped, a quarter needed only a theme fragment or CSS, and nine bodies of work were scheduled. Two ADRs came out of it — ADR-0083 (dependencies) and ADR-0084 (Effects).

Body of work Verdict Reduces to Note
Corrections and updates per post rejected in its cheap form, parked in its real one Effect corrections-from-history.md. A hand-maintained frontmatter list misleads where none would not; deriving it from repository history waits on the Effect runner and on whether the engine may read git at all. Per-post edit history is parked in that same file
Per-piece template variants the highest-value item in the list View Scheduled, not parked: the second concrete use that earns the View primitive, and roadmap.md closes Arc 2 when it lands
Bengali morphology for search original work, not a sub-task bengali-search-morphology.md. Exact-form search is scheduled without it and documents its own absence

Parked, with triggers

Each of these was reviewed and deliberately not scheduled. The trigger is what would change that — a condition, not a mood.

Item Trigger What was decided
Date-grouped listings wanting any one of: a cross-page timeline, a yearly wrap-up, a date-grouped archive One partition beside the existing section one serves all three, following ADR-0046's rule that the engine partitions and the theme decides whether it looks grouped. Individually none justifies the work
Inline code highlighting writing enough technical prose to feel the lack Syntax settled in advance: a trailing attribute block — `code`{lang=python} — never a marker inside the span, since a code span is literal and this engine's recurring defect is new syntax eating prose. Matches Pandoc/Djot and the existing ## Title {#id} form. Wants its own ADR, because authored syntax is a contract with the author's files
Ruby annotations for glosses the free path failing Works today via raw HTML. The zero-cost path first: a theme rendering existing *[TERM]: abbreviations as <ruby>, since a gloss above versus on hover is presentation over data already collected. Caveat: abbreviations expand at every occurrence. Standing note — the inline delimiter budget is nearly spent (~ ^ = * all taken), which argues against inventing marks
Archive.org snapshot links beside external links something wanting a pass over authored anchors more than this does Needs a parse-phase walk over link nodes; a theme cannot do it. Modest value. Distinct from submitting links, which is scheduled
JSON Feed a reader or client you actually use asking for it Atom covers every consumer. /feed.json site-wide is an exact path and could be a feature cheaply; section and tag scopes are resolver cases, so decide it with that seam
Content as data / a personal JSON API wanting it for its own sake The human's own framing: "a cool geeky thing", may never be used. The sovereignty argument for it is wrong — the raw Markdown in his git already is the sovereignty. /all.json site-wide is an exact-path escape; per-bundle is resolver-gated
oEmbed building the capture feature below Reframed: not a render-time embed, which ADR-0080 refuses, but capture-time metadata discovery — how a snapshot learns a URL's title, author and thumbnail
Static copies of external content wanting to quote something that may vanish Engine-produced, not by another tool. Shape decided: a khosra snapshot subcommand following scaffold's precedent for writing to the site root, into the bundle rather than the disposable cache since a snapshot must outlive its source, storing sanitised text, image and attribution — never the remote HTML, which would execute, because site-root content is trusted by location (ADR-0060)
Image processing, as one cluster any one of them mattering Cropping (a parameter on the derivative pass, folded into the content hash), EXIF display (the engine already inspects every image for dimensions, so this extends a shipped pass), a view-full-resolution link (nearly free — the original is already src), before/after comparison (CSS-only variants exist; the draggable one is JS and refused), and the AVIF gap (no Go decoder, so it passes through unresized). Clustered at the human's request rather than scattered
POSSE back-links wanting a page to link its own copies Syndication itself is absorbed by the scheduled notify work — n8n posts to platforms. The residual is u-syndication: recording where copies live, which needs somewhere to put the URLs
Micropub wanting to publish from a phone The endpoint is easy; IndieAuth is the bulk. Persistence is not a blocker and the resolution is recorded: the engine writes through os.Root (scaffold's precedent) and the operator's existing pull/commit picks it up, so the engine still never touches git
"View as Markdown" / raw source per post the comment problem being solved ?raw on the existing bundle URL avoids inventing a resolver path and reuses the convention extras already use. Blocked on a leak: HTML comments in content are published verbatim today (verified), so serving raw source would expose anything commented out. The scheduled check warning is the prerequisite
IndexNow ping on publish caring about Bing and Yandex An outbound Effect, nearly free once the dispatcher exists. Honest limit: Google ignores IndexNow, so it is cheap and marginal rather than cheap and valuable
Blogroll and OPML export wanting others to subscribe to your whole list The blogroll is content and free today. OPML is one marshaller at an exact path, so a feature with no core growth
Random post wanting a discovery affordance One exact-path route, architecturally free, and honestly a toy. Note: randomness deserves the containment time.Now() already gets — verify.sh confines the clock to clock.go because ambient nondeterminism hides staleness

Dropped, with reasons

Kept because a one-line reason is the cheapest defence against relitigating a decision in four months.

Item Why
EPUB generation Calibre, Pandoc and percollate already convert web to EPUB. The engine's real contribution is structure — sequences already publish reading order — so the revisit trigger is "external tools produce a bad book", not "want EPUB"
Gemtext output Readership is approximately zero, and its only real value was proving a View can target something other than HTML. Not worth carrying for that
Static export Cannot serve Arc 3's write endpoints or in-memory search, so it is a second permanently crippled product rather than a hedge. The hosting insurance it appears to buy already exists: Markdown in git, one portable binary
Incremental rebuilds A whole page renders in ~63µs. This solves a build measured in minutes, a scale this site will notice instantly if it ever reaches
Live reload Buys not pressing refresh, at the price of JS or SSE on every page — and the rebuild already lands within one poll
Self-hosted analytics counting Write-on-read means state and IO on the hot path. Access logs contain every fact a counter would, cost zero engine code, and leak nothing. goaccess answers it in an afternoon
Incoming rebuild webhook Polling already covers it, so this spends a write endpoint, the untrusted boundary and rate limiting to save two seconds
Outgoing chat webhooks as a general system Absorbed: the scheduled notify Effect emits events and n8n owns routing, formatting and per-platform posting. A configurable per-target rule engine in the engine would serve one caller forever
Twitter cards, meta description Theme work once .Summary exists; Twitter reads the OpenGraph already emitted
Design tokens, print stylesheet, columnar layout, in-page timeline All CSS or a theme-defined container, in a file the engine does not own (ADR-0023)
Copy-to-clipboard on code blocks, Cmd+K palette JS on ordinary pages, refused by ADR-0080. The palette also needs search first, and the search page is one keystroke from the address bar
WebSub (rel="hub") Push instead of polling for feeds, at a scale this site does not have
Writing stats page "Just for fun" by the human's own framing, the same standard that dropped readability scoring

Catalog

IndieWeb — Micropub★, Microsub, Webmention, WebSub, microformats2, IndieAuth, rel=me, PESOS/POSSE, Bridgy and Bridgy Fed, Vouch.

Protocols — Gemini + gemtext★, Gopher, Nostr (NIP-23 long-form), ActivityPub (trunk), AT Protocol, SSB, Solid (trunk), IPFS (trunk), Hypercore, content negotiation (one URL → many formats).

Small web and discovery — webrings, guestbooks, 88×31 buttons, finger, tildeverse, OPML blogroll★, full-text feeds★ (for indie search indexing: Marginalia, Kagi Small Web, ooh.directory, indieblog.page, feedle, powRSS), random / "surprise me", /now pages.

Reading and annotation — Web Annotation + Hypothesis (hosted = trunk), reading progress, interlinear and parallel translation.

Permanence — outbound-link archiving★, WARC self-archive, Memento over git, permalink discipline, exposed revision history.

Identity and integrity — rel=me, Keyoxide, signing (age/minisign/PGP), C2PA, DIDs.

Feeds and data — RSS/Atom, JSON Feed, h-feed, OPDS (publication catalog), JSON-LD and schema.org, OpenGraph, Dublin Core, sitemaps, RSS-to-email.

Page as program — Ink★, Twine, Inform 7, PICO-8/TIC-80, Godot HTML5 embeds, explorable explanations, TiddlyWiki and single-file artifacts.

Print — Typst, Pandoc, EPUB and PDF chapbooks, on-demand anthologies.

Client side — View Transitions★ (palette-shift-as-navigation), Houdini, Canvas, WebGL, WebGPU, modern CSS, WASM, islands, HTMX, Web Components, PWA offline, prefetch, accessibility and prefers-reduced-motion.

Build time — SQLite FTS5, Pagefind, sqlite-wasm + OPFS, Djot, Templ, libvips, ThumbHash and BlurHash, content-addressed and Merkle builds, Datasette, CRDTs (heavy, trunk).

Aesthetic — dithering and palette Stage★, ANSI/PETSCII, teletext, demoscene, e-ink View.

Valuesrobots.txt / ai.txt (training control), llms.txt (low proven impact), sustainable and low-carbon web, privacy-respecting analytics or none at all, sovereignty, sneakernet and QR offline distribution.

Standing notes

  • Bengali tokenisation for search is the one item here nobody else will solve for you. Treat it as original work, not as a checkbox inside "add search."
  • Micropub before an admin panel. It buys an ecosystem of existing editors for the price of one endpoint, and it composes with git instead of fighting it.
  • Gemini output is nearly free once the View layer exists, and it validates the claim that a View can target something other than HTML. Good early proof, low cost.

Shapes recorded before anything asked for them

Moved out of harness/content-model.md, which now describes only what the parser accepts. Each is intent, not a plan: the shape is decided by whatever eventually builds it, and being written here is not permission.

Galleries, collections [spec]

Both are a Query over bundle metadata with a stable sort; neither justifies a new primitive. A gallery is a Query plus an image View. Related posts are a Query with a scoring function, not a stored graph.

Taxonomies [spec]

Two kinds, deliberately. Recorded intent (ideas/deferred-decisions.md), not built.

tags are one global namespace across every type. /tags/{tag}/ lists everything carrying the tag; /{section}/tags/{tag}/ narrows it; listing views group results by type so a busy tag stays readable. Cross-type discovery is the point — one tag spanning a comic, a poem and a photo essay is a feature here, not noise. Term slugs are derived by locale and overridable by hand (ADR-0015).

Declared taxonomies are structural: a fixed term set that changes engine behaviour, declared on the type — series for ordering, medium for art, genre for writing. These never enter the tag pool. The test: a tag is free-form and cross-cutting, a declared taxonomy has known terms and drives behaviour.

Feeds follow the same shape: /tags/{tag}/feed.xml comes free from the same Query as the listing.

Time-dependent presentation [spec]

Anything derivable from a page plus the current clock is computed by a Stage, never stored in content: an "this article is old" banner compares date to now, relative dates likewise. Because renders are cached (ADR-0005), such a Stage also declares how long its output stays true — a banner until date+threshold, a relative date for a minute — and the cached entry expires then. Future-dated publication is the same shape seen from the other side: the page becomes reachable at a moment nobody is requesting it.

Below the site level [spec]

Section-level and bundle-level settings are not built: a bundle's own frontmatter covers it, and nothing reads a section override yet. The parked shape is site → section → bundle, nearest explicit value winning (ideas/deferred-decisions.md).

Level Where it lives
site site.yaml at the site root
section, and any enclosing section that directory's _index.<lang>.md frontmatter
bundle the bundle's own frontmatter

The cascade carries stage toggles, view selection, taxonomy defaults, cache flags, and metadata defaults — declared keys only, never arbitrary engine internals. Stages run on everything by default and are switched off by a cascade key, not by a predicate inside the stage: a stage that finds nothing to do returns early on content shape ("no images here"), which has nothing to do with type.

This is also how a template is chosen: type default, then section override, then the bundle's view (ADR-0019).