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>
This commit is contained in:
2026-08-03 16:14:52 +06:00
co-authored by Claude Opus 5
parent c6c3f0aa3f
commit b313b729d9
15 changed files with 556 additions and 385 deletions
+50 -5
View File
@@ -18,14 +18,59 @@ Use `/leaf <topic>` to get a verdict written into this file.
## Verdicts
One row per body of work triaged, not per item — the item-level verdicts live in the file each row names,
because 130 rows here would make a catalogue nobody can skim.
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 |
|---|---|---|---|
| The human's feature list, 130 items | triaged in full | mostly nothing new | [feature-list-triage.md](feature-list-triage.md): 42 BUILT, 24 THEME (a fragment or CSS, no engine code), 29 LEAF, 2 TRUNK, 4 PARK. Three LEAF items have shipped since — task lists (ADR-0078), page assets (ADR-0079), passthrough routes (ADR-0081) |
| Corrections and updates per post | **rejected in its cheap form**, parked in its real one | Effect | [corrections-from-history.md](corrections-from-history.md). A hand-maintained frontmatter list was dropped because a half-remembered list of corrections 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-piece template variants | the highest-value item in the list | **View** | Not parked — it is the second concrete use that earns the View primitive, and `harness/roadmap.md` closes Arc 2 when that lands. Tracked as scheduled work, not as an idea |
| Corrections and updates per post | **rejected in its cheap form**, parked in its real one | Effect | [corrections-from-history.md](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](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