Files
khosra/ideas/feature-list-triage.md
T
bdeshiandClaude Opus 5 949ce34224 give pending work four owners instead of six scattered lists
Ideas were spread across six places with real duplication and one list that was
about to be lost. Consolidated by merging the duplication, not the categories.

The 130-item feature-list triage lived in .scratch/, which is gitignored — 130
verified verdicts a scratchpad cleanup would have deleted. It is now
ideas/feature-list-triage.md with the header the ideas gates require, indexed,
and out of agent context by default like everything there. exploration.md's
Verdicts table was empty and designed for exactly this; it now carries one row per
body of work with a pointer, rather than 130 rows nobody could skim.

Deferred triggers had no single owner: continue.md restated them and drifted,
still listing the extension registry as pending after ADR-0081 built it.
deferred-decisions.md now holds the only trigger table, covering the two it
already described plus math, corrections, write routes and the registry's
remaining fields. continue.md links to it. Two rows record couplings worth not
rediscovering: the View layer may pull a minimal settings cascade in with it,
because the Views counter says selection resolves *through* the cascade; and
ADR-0081's seam mounts GET only, so Arc 3's first write endpoint extends it.

Corrections per post is dropped in its cheap form and parked in its real one. A
hand-maintained frontmatter list was rejected for an authoring reason rather than
a technical one — a half-remembered list of corrections misleads where none would
not, because two entries imply those were the only two. Deriving it from
repository history is the shape worth waiting for, and the file records what must
be settled first: whether the engine may read local git history at all, that it
needs a dependency or a subprocess, and that not every commit is a correction.

Not merged, on purpose: latent items stay in state.md because they describe
shipped code and are gated against .go commits; arcs stay in roadmap.md because
they are sequencing decisions. One file would have flattened four levels of
authority and made pending work cheap to load, which is the opposite of why
ideas/ sits outside harness/ at all. harness/README.md now says which list owns
what, in both the topic table and the single-source table.

7 files. No rule or threshold moved.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 23:31:24 +06:00

33 KiB
Raw Blame History

Feature-list triage

Status: catalog — one verdict per item, overridden by the answers at the top Raised: 2026-08-02

Every item from the human's feature list, with a verdict. Not a plan and not a queue — nothing here has authority over the code, and being listed earns nothing. It lives in ideas/ because that is where work nobody has committed to belongs, and it is out of agent context by default like everything else here.

Summary counts, which ideas/exploration.md also carries: 130 rows — 42 BUILT, 24 THEME, 29 LEAF, 2 TRUNK, 4 PARK, 4 CONFLICT (all four now resolved). Three of the LEAF items have since shipped.

Verified against the code on 2026-08-02, not against state.md. Where a verdict says BUILT it means the code does it, and the citation is where to look.

Detail volume was normalised deliberately. The longest section (Content-specific) is mostly frontmatter that already works plus one genuine primitive; the shortest line in the whole list ("Search") is the largest single piece of work in it.

Answered 2026-08-02 — these override the verdicts below

  1. Categories: sections are categories. No second taxonomy. Every "categories" row below resolves to BUILT, and the tag axis stays the only non-structural one.

  2. Private: dropped entirely. No secret links, no capability URLs — ADR-0024 stands untouched. draft plus unlisted covers the ground, so unlisted survives as a small LEAF and private/archived leave the list.

  3. Task lists: enabled, superseding ADR-0058's exclusion. The TaskList extension only. Linkify and the rest of the GFM bundle stay out — linkify rewrites an author's plain text into markup, which is the line ADR-0034 draws and is a separate decision from this one.

  4. JS: a small page-scoped exception is allowed. Opt-in per page via frontmatter, never site-wide, which requires the styles/scripts fields to be actually lifted. The antifeature list must be written down with the exception in it — an exception nobody recorded is how the whole list erodes.

  5. Git sync stays out of the engine. content-model.md's position is untouched: something else pulls, the engine notices the changed files and rebuilds, which already works. No credentials in the engine and no write path to the content repo. The "incoming webhook" half remains an Arc 3 question, not a git one.

  6. Shared parts between bundles: left blocked, deliberately. Not worth a permanent disk-contract decision yet. So cross-document jargon tooltips and the worldbuilding glossary are PARK, and abbreviations stay per-document as ADR-0062 has them. Revisit when something being written needs it.

  7. The Extras section is live scope, not a remember-these-exist list — the human overrode their own header. Its verdicts below stand as real candidates.

The decided small batch is done (69f43e5, 64e53f2): task lists enabled superseding ADR-0058, the antifeature list recorded as ADR-0080 with its one exception, and page assets shipped as ADR-0079 — theme assets:<name> fragments pulled in by the shortcodes that need them or by use:, plus the bundle's own styles/scripts, lifted at last. Unlisted was dropped. So every verdict below tagged THEME for a shortcode needing CSS or JS is now genuinely reachable without engine work.

Unstarted, in no fixed order: the View layer (closes Arc 2), raw passthrough routes, corrections/updates per post.

Still open: whether to fix SKILL.md's stale three-question cap (CLAUDE.md §4 uncapped it in 25d7045); declared content types (queue 7), which is what "alt text and content warnings first-class per type" needs.

Verdict key

Tag Means
BUILT Ships today. Cited.
THEME A theme fragment, template or CSS. No engine code, no rebuild — proven below.
LEAF Engine work that reduces to an existing primitive. Buildable when wanted.
TRUNK Wants a permanent service or a core-model change. Needs a deliberate decision in an ADR.
PARK Real but not now. ideas/exploration.md.
CONFLICT Contradicts a recorded decision. Surfaced, never resolved silently (CLAUDE.md rule 9).
? Needs an answer before it can be classified.

The one verification that reframes the list

A shortcode name the engine has never heard of renders from a theme fragment alone, and the fragment hot-swaps while the server runs:

::spoiler{summary="Chapter 3 twist" body="She was the lighthouse."}
+ templates/shortcodes/spoiler.html   →   renders, no engine code, no rebuild
edit the fragment with the server up  →   new output in one poll interval

The parser's switch on name only enriches three names (gallery reads the directory, figure inspects a picture, include marks content). Every other name becomes a node and renders through a fragment of that name; a name the theme does not define renders nothing and logs it (internal/ext/shortcodes/shortcodes.go, content-model.md Shortcodes).

So "lightweight shortcode mechanism, loaded as data/templates rather than hardcoded, so I can add one without a rebuild" is already built exactly as specified — and any item that is "render this markup from these arguments" is a fragment you write, not a feature I build.


Content

Item Verdict Justification
post / page / note / project as separate types BUILT as convention Sections are the type: content-model.md Post types already names post/comic/art/writing/page/status, defaulting from the top-level directory. note/ and project/ are two mkdirs. A declared type file with per-type defaults is deferred (queue 7, ideas/deferred-decisions.md) and waits for a dated bundle needing to stay out of a feed
Tags BUILT Flat, case- and script-preserved, slugged for URLs (ADR-0018); listings global and section-narrowed, paginated, with per-tag Atom feeds (ADR-0043)
Categories ? See question 1. My read: sections already are categories — one per post, structural, in the URL. A second single-select axis buys a routing case and a listing shape you already have
Series with its own ordered index BUILT Sequence: structural membership by nesting (ADR-0033), order ascending sparse, prev/next/first/last/count, series archive on any nested bundle, resolving through language fallback (ADR-0016)
Page status: draft BUILT Lifted to Bundle.Draft; 404 for the bundle and every file inside it (ADR-0024); -dev on reveals. Future-dating works the same way and expires per request
Page status: unlisted LEAF, small Served at its URL, absent from listings, feeds and sitemap. No conflict — it is a query-membership flag, and Site.Run is already the one place membership is decided
Page status: private via secret link CONFLICT ADR-0024 chose 404 over 403 for unpublished work specifically so existence is not confirmed. A secret link serves unpublished content to whoever holds the URL, which is a capability-URL design (unguessable token, no listing, no sitemap, noindex) and a different security model. Question 2
Page status: archived THEME A frontmatter flag the template reads. Nothing engine-side unless it changes query membership, in which case it is unlisted above
Page inclusion — embed one fragment in another BUILT ::include{file=…}; merging is the default so the page is one document (ADR-0066, ADR-0076), include: embed for containment. One level, no .., missing file logs and still serves
Per-page custom CSS/JS for demos THEME today, LEAF to formalise styles/scripts are in content-model.md's table but not lifted — verified: nothing in internal/ reads them, so they sit in Extra, which the theme can already read (ADR-0002 open page object). Lifting them properly is a small LEAF. Consistent with your antifeature: JS for demos only
Folder-per-post browsable extras BUILT, precisely as described extras/ (ADR-0047): scanner skips it, enumerated as a sorted tree, classified markdown/text/image/pdf/audio/video/other/dir, markdown and text rendered, everything else offered as bytes, ?raw for the file itself, excluded from queries/feeds/sitemaps. Your "old drafts, notes, worldbuilding material, reference lists, code samples" is the exact use it was built for
Inline image alignment / sizing THEME The figure fragment plus CSS classes. left/right/center/full-width is layout, and ADR-0045 is the precedent for not doing layout in the engine
— cropped LEAF The one part that is not CSS: derivatives are width-only today (ADR-0042). A crop is a new operation on the existing pass
EPUB export LEAF Genuinely new. An Effect writing an artifact: archive/zip and XHTML are stdlib, so no dependency. Wants the Effect runner (counter at 1, due at 2)
Server-rendered QR code LEAF Self-contained, no client JS, fits the values. ~200 lines hand-rolled, or a dependency needing an ADR. Nice small win

Authoring

Item Verdict Justification
Markdown + footnotes, tables BUILT CommonMark plus tables, footnotes, definition lists, heading ids declared or derived (ADR-0058). Footnote ids namespace per included file
— task lists CONFLICT ADR-0058 excluded them deliberately: "a note-taking affordance, not a publishing one", and the GFM bundle was refused because it drags task lists and linkify in with the tables. Question 3
Frontmatter fields BUILT Unknown keys land in Extra and templates read them (ADR-0002). Most of the Content-specific section below needs nothing more than this
TOC generation BUILT ::toc, ::toc{depth=2}; entries carry level, text without markup, and the id the engine assigned, so indentation is CSS (ADR-0065, ADR-0066)
Reading time, word count LEAF, tiny — and notable These are the first page-level transforms, the same slot as OpenGraph/JSON-LD (queue 15). The transform counter is at 0 of 3, so this is one of the three things that would earn the Stage pipeline
Image galleries BUILT ::gallery lists pictures beside the bundle in filename order; subdirectories and unshowable files excluded (ADR-0016)
oEmbed-style embeds TRUNK, and your own list answers it The engine never fetches — content-model.md: "It never fetches them. Pulling a git repository is the operator's business". Also collides with your antifeature about third-party embeds. Your "static self-rendered copies" is the right answer; see below
Typography: smart quotes, dashes BUILT goldmark typographer on the parsed tree, so code spans keep straight quotes and -- (ADR-0034)
— widow/orphan control CSS, and settled You already say "mostly CSS", and you are right for a recorded reason: ADR-0045 deleted a shipped engine feature for this. text-wrap: pretty/balance in theme.css does it
Lightweight shortcode mechanism, no rebuild BUILT Verified this session, see above. This is the highest-value already-built finding in the list
Timeline within a single page THEME A container shortcode over authored entries. Zero engine code
Timeline across pages / series LEAF A Query (already earned) plus a listing shape. The genuinely new half of that bullet — worth splitting from the other
admonitions, info boxes, tabs BUILT :::note, :::warn, :::tip, :::details — and siblings sharing a group render as tabs — plus :::aside for margin notes (ADR-0064). A kind the theme does not define renders its body unwrapped rather than losing it
Static self-rendered copies of external content Reframe → THEME As an engine fetch it is a TRUNK (see oEmbed). As content it is free: an external tool snapshots the tweet into the bundle, and a fragment renders it. Same reader benefit, no outbound capability, no trust boundary. Strong recommendation
Inline code highlighting via a marker LEAF, small Block highlighting is built (chroma, ADR-0075). Caution: your proposed `{lang=python}…` is exactly the "what prose does this eat?" failure mode — five defects this project has already shipped were new syntax swallowing ordinary text
Ruby annotations LEAF, small An inline mark in internal/ext/notation/, which owns exactly this (ADR-0061), or a fragment if you accept a shortcode call instead of terse syntax
Strikeout and highlight BUILT ~~struck~~ and ==marked==, khosra's own so a single tilde can mean subscript (ADR-0061)
Columnar layout THEME CSS columns
Archive.org link beside external links split Rendering the link: THEME. Auto-submitting on publish: LEAF after the Effect runner, and outbound to a third party
Readability score EN/BN PARK English is easy. Bengali is not, and roadmap.md flags Bengali tokenisation as the genuinely novel problem in this project — do not solve it as a side effect of a stats page

Multilingual

Item Verdict Justification
EN/BN pairing between translations BUILT Language variants per bundle key, fallback requested → default → any → 404 (ADR-0004), English at root and /bn/ prefix with /en/… redirecting (ADR-0009)
Script-aware typography per language BUILT (chrome) + CSS (body) Chrome, dates and digits localise from an engine table — পৃষ্ঠা ২ / ২, ৮ মার্চ ২০২৬ (ADR-0034). Authored text is deliberately never localised. Per-script typography is CSS, and the lang the theme needs is already on the fragment (ADR-0067)
hreflang BUILT Emitted from the variants that exist, absolute once base is declared (ADR-0039)

Theming

Item Verdict Justification
Partials / includes BUILT Fragments and Partial in the theme contract; shortcode fragments may be one file or a directory (ADR-0071)
Dark / light via prefers-color-scheme BUILT Present in theme.css — verified
Design tokens instead of hardcoded CSS THEME Custom properties. theme.css is yours to restructure; the engine has no opinion
Print stylesheet THEME Not written. Pure CSS

Discovery

Item Verdict Justification
Archive pages for tags BUILT Global and section-narrowed tag listings, paginated at /{section}/page/N/ (ADR-0028)
Search LEAF — and the largest item in this list One word, arc-sized. roadmap.md: "Bengali tokenisation for search is the genuinely novel problem here — solve it well and deliberately, not as a side effect of adding search." Needs an index (an Effect), a query path, and a real decision about conjunct normalisation beyond NFC
RSS / Atom feeds BUILT Atom per site, section and tag, from dated bundles via one Query (ADR-0043)
JSON Feed LEAF, tiny One more marshaller. Note state.md: output formats deliberately do not count toward the Views counter — three functions with nothing to share
Sitemap BUILT Every bundle in every language it exists in, lastmod where dated, 404 without base (ADR-0039)

SEO

Item Verdict Justification
OG tags BUILT Emitted from fields already on the page, absolute with base
Meta descriptions THEME From summary or derived. No new disk field — content-model.md is explicit that SEO adds no frontmatter
Twitter cards, JSON-LD LEAF — the Arc 2 mover content-model.md: "no consumer yet". These are queue 15, the first page-level transforms, and they take the transform counter off 0 toward 3. Also the trigger for the latent item that the counters have no mechanical check
Canonical URLs BUILT Canonical plus trailing-slash canonicalisation, one rule applied once
Redirect handling BUILT aliases → permanent redirects; ambiguity logged and dropped rather than fatal (ADR-0008, ADR-0029)
Content as data — text / JSON / YAML LEAF Output formats. Same feature as "Personal JSON API" in Extras — one build, two list entries

Performance

Item Verdict Justification
Cache Deliberately not built "No cache until requests feel slow." A whole page renders in ~63µs (ADR-0044), and a latent item explicitly declines to memoise sequence resolution for want of a measurement. Adding one now would be a cache with no number behind it
Static export LEAF Useful independently of caching — it is a deploy artifact and an offline copy. Reduces to Query + Effect
Responsive images BUILT Three widths, never upscaled, content-hash names, srcset closed by the original, width/height from the source so the box is reserved (ADR-0040, ADR-0042)
Native lazy loading THEME One attribute in the figure/gallery fragment
Incremental rebuilds PARK with a trigger The rebuild is a whole-index swap and is not what costs anything. Revisit when a rebuild is felt — the same trigger that would revive the parked cache

Routing

Item Verdict Justification
Raw passthrough routes, incl. .well-known/* LEAF — highest leverage small item in the list static/ only answers under /static/; nothing can be served at /pubkey or /.well-known/security.txt. This one feature satisfies four separate entries: /pubkey, humans.txt, security.txt, and the PGP page. Needs care: the root is engine-owned (ADR-0008, ADR-0050), so it wants an explicit reserved-path story rather than a catch-all
Short / alias URLs with redirects BUILT aliases, any number, permanent redirects, ambiguity logged and dropped

Events

Item Verdict Justification
Hook points (on publish, on webmention) LEAF The Effect primitive. Counter at 1 (the derivative pass), runner due at 2 — so the second Effect earns the trigger wiring rather than inventing it
Outgoing webhooks (Slack, Telegram, custom) LEAF after the runner Outbound HTTP with per-target rules. Sequence it after the runner exists or it becomes the runner
Incoming webhooks (git push → rebuild) Arc 3 A write endpoint, therefore the untrusted boundary (ADR-0003) and rate limiting. Not a small addition to a read-only server
Auto-submit external links to archive.org LEAF after the runner Outbound Effect, third-party dependency at runtime
Git pull / push sync CONFLICT content-model.md: "The engine notices changes. It never fetches them — pulling a git repository is the operator's business, not the engine's." A deliberate position, and reversing it means the engine holds credentials and can rewrite the author's data. Question in chat
Auto-flag old pages THEME — free today And it is roadmap.md's own worked example: "An 'old article' banner is a Stage; it needs no job and can never be stale." Computable from the page plus the clock, so the template does it with the date it already has

Interactivity

Item Verdict Justification
Server-processed forms Arc 3 The Interaction primitive, with ADR-0003's boundary. Fields, validation, action target — plus rate limiting and spam handling, which is why they are one arc and not one feature
Webmention replies / reactions Arc 3 The canonical first Interaction; roadmap.md already sequences it
Client JS for demos only Already the position The reference theme ships no assets and no JS: icons are Unicode (ADR-0063), highlighting is server-side (ADR-0075), the TOC and the contents list are server-rendered, tabs and reveal panels are details with no script

IndieWeb

Item Verdict Justification
Webmention send/receive, Micropub, POSSE, mf2 Arc 3 / 4 roadmap.md puts Micropub first on purpose: it buys an existing editor ecosystem and needs no UI, which may remove the admin panel entirely
ActivityPub TRUNK — already recorded as one ideas/exploration.md lists it among known trunks. Your "only if it sparks joy" and the sovereignty test agree. Your instinct that it needs its own actor/inbox/signing mechanism rather than the generic webhook path is correct and is why it is a trunk
Gemtext LEAF An output format, and ideas/exploration.md stars Gemini as high fit-to-effort for this project's values

Admin

Item Verdict Justification
Dev server BUILT -dev on reveals drafts and future-dated bundles and polls 4×/s; content and templates swap atomically as one snapshot, so a template typo keeps the last working theme instead of taking the site down (ADR-0055, ADR-0056, ADR-0077)
Live reload (browser auto-refresh) Tension Needs JS or SSE on every page, against your own antifeature. The rebuild already happens in one poll; a manual refresh costs nothing. Recommend dropping it
Git as source of truth BUILT by design The site root is its own repository, passed with -site; nothing in the engine repo is content (ADR-0011)
Link / frontmatter checks BUILT khosra check: engine workarounds, broken internal links, missing titles, missing alt text, mixed series ordering, retired shortcode calls. Non-zero exit, and verify.sh runs it over the demo site

Security & Ops

Item Verdict Justification
Rate limiting on write endpoints Arc 3 Arrives with the first write endpoint, not before — there is nothing to limit on a read-only server
Spam filtering on webmentions Arc 3 With receive. Your honeypot-and-rate-limit stance beats CAPTCHA and is already in the antifeatures
Backups Operator, not engine ADR-0010's sovereignty line. The content is a git repo; the derivative cache is disposable by construction (content-hash names)

Analytics

Item Verdict Justification
Self-hosted / simple counting LEAF, with a cheaper alternative A counter is a write on the read path — state, IO, and a concurrency question the engine has deliberately avoided. Parsing access logs offline costs zero engine code and answers the same question. Recommend the log route first

Antifeatures

Every one is consistent with a decision already recorded, and several are enforced rather than intended: no JS or assets in the reference theme (ADR-0063), server-side highlighting (ADR-0075), server-side TOC (ADR-0065), no trackers therefore no cookie banner, server-side over client-side as the standing preference.

Recommendation: record the list as an ADR. An antifeature that is not written down does not bind a future decision, and this list is exactly the kind of thing an agent will erode one reasonable-looking request at a time. It is also the cheapest ADR in the backlog — a decision you have already made.

One internal tension: "no hover-preview popups (the gwern.net thing)" versus Extras' "hover-preview footnotes/sidenotes". Adjacent but arguably different — a footnote is your own text, a link preview is someone else's page. Worth resolving explicitly in the ADR, and note :::aside already gives you server-rendered margin notes with no JS at all.


Extras

Item Verdict Justification
Now / Uses / Colophon pages BUILT Ordinary bundles under pages/. The demo site already has pages/colophon
Guestbook Arc 3 Forms or webmention; piggybacking on that infrastructure is right
Blogroll, OPML export THEME + tiny LEAF The list is content; OPML is one more output format
Link blog BUILT as convention A section plus a type. Nothing to build
TIL BUILT as convention Same
Digital-garden backlinks Arc 4 roadmap.md names backlinks and transclusion there. Needs a link graph over the index — a real feature, arc-gated, and transclusion needs a cycle guard
Random post LEAF, tiny One route. Note the discipline: time.Now() is confined to clock.go and verify.sh enforces it by filename; randomness deserves the same containment
Yearly wrap-up LEAF, small A Query by date range plus a listing. The Query primitive is already earned
Site changelog THEME / content A page you write, or git log of the content repo rendered — the latter shares the git-reading question with per-post edit history
Personal JSON API LEAF Same feature as "content as data" under SEO
Reading / watching / listening log BUILT as convention A section plus frontmatter
Writing stats page LEAF, small Query plus arithmetic. Pairs with word count
Command-palette search (Cmd+K) Tension, and gated Needs JS on every page, against the antifeature — and needs Search to exist first
Sticky / floating TOC THEME position: sticky. The TOC data already exists server-side
Hover-preview footnotes / sidenotes THEME Achievable with CSS alone, and :::aside already does margin notes. See the antifeature tension above
Copy link / share button THEME A plain link needs no JS; the clipboard does
404 with personality THEME The 404 path exists and is tested; the words are the theme's
humans.txt / security.txt LEAF The raw-passthrough route. Same one feature
IndexNow-style ping on publish LEAF after the Effect runner Outbound
PGP / identity proof page LEAF The raw-passthrough route again
EXIF display on photo posts LEAF — cheaper than it looks The engine already opens and inspects every picture for width/height, memoised and LRU-bounded (ADR-0042, ADR-0044, memo.go). EXIF extends an existing pass rather than adding one

Content-specific

Tech writing

Item Verdict Justification
Copy-to-clipboard on code blocks Tension Needs JS. ~10 lines, but it is JS on ordinary pages, which your antifeatures rule out. Your call, not mine to soften
Line highlighting in code blocks BUILT hl=3,7-9, in the numbering the reader sees, plus title=, numbers=, start=, file=, lines= (ADR-0075)
"View as Markdown" / raw source per post LEAF, small The pattern exists: extras already serve ?raw. Extending it to a bundle body is a route, not a redesign
Corrections / updates section per post THEME today A frontmatter list plus a fragment. No engine code. And the right call for credibility — I would build this before most of the list
Per-post edit history LEAF / ? Means the engine reads git, which it does not do today. Either an Effect writes a history file, or this stays the operator's. Shares the question with git sync
Inline diagrams as a figure template BUILT ::figure{src alt caption} is exactly image + caption + alt
Jargon / acronym tooltips BUILT for one document, gap across documents *[TERM]: definition expands every whole-word use and renders <abbr> (ADR-0062) — tooltip is the browser's title. But a definition applies to that document only, and content-model.md names sharing a fragment between bundles as deliberately not possible yet: it needs somewhere to keep shared parts, which is a disk-contract decision. That gap is the real feature behind both this and the worldbuilding glossary
Sandboxed runnable demos THEME + the styles/scripts lift An iframe is markup. Isolation is the iframe's, not the engine's

Comics

Item Verdict Justification
Numbered index, newest first, numbering independent of date BUILT order is position and never appears in a URL (ADR-0016); listings sort by date, sequences ascend by order. The two are already separate
One per page, next / prev BUILT Sequence navigation on any nested bundle, resolving through language fallback
— random LEAF, tiny One route
— grid when more than one per page THEME Layout
Panels, some hidden until revealed BUILT :::details — an expandable panel with no JavaScript (ADR-0064)
Description and alt text as separate fields THEME today Both live in Extra; the template decides which goes to alt and which to prose. khosra check already fails on missing alt text
Serialized arcs alongside one-offs Agreed open — and a content question You call it open and I think you are right to. Worth noting why it is cheap to defer: membership is structural (ADR-0033), so an arc is a nested directory and a one-off is not. The archive's reading order is a theme decision on top of data that already exists. Decide it with real content in front of you

Artwork

Item Verdict Justification
Gallery / grid view BUILT + THEME ::gallery gathers; grid is CSS
Lightbox THEME An <a> to the original is the no-JS version and also gives you "view full resolution"
Per-piece metadata (medium, tools, dimensions) BUILT The Extra bag, by design (ADR-0002)
Before / after slider THEME CSS-only versions exist; the draggable one is JS. Useful beyond art, as you say
"View full resolution" link BUILT-able, one line The original is already src and the derivatives are the srcset — the full-res file is already addressable
Attribution / license per piece THEME Extra plus a fragment
Alt text as a real description, required for this type BUILT (checked) + ? (per-type requirement) khosra check already fails on missing alt text everywhere. Making it required for art specifically needs declared types (queue 7)

Creative writing

Item Verdict Justification
Per-piece template variants — letter, terminal log, clipping LEAF — and the most significant item in the list This is the View layer: view: in frontmatter choosing a presentation, architecture.md's named primitive, counter at 0 of 2. Your Cross-cutting bullet restates it, which makes it the second concrete use — the thing that earns the primitive. Arc 2 closes when the View layer lands, and that is where the core stops growing (roadmap.md). You independently asked for the exact feature the roadmap was waiting for, and your framing — one content model, variants layered on top, not a content type per variant — matches the ADR-0023 contract already frozen for it
Story status: ongoing / complete / hiatus THEME Extra plus the series index template
Worldbuilding glossary with inline definitions BUILT for one document, same cross-document gap as jargon tooltips See above — the shared-fragment decision is the real blocker for both
Content warnings THEME today, ? for first-class A frontmatter field works now. "First-class across all four types" means enforced, which needs declared types (queue 7)
Epigraphs / dedications THEME Extra plus a fragment

Cross-cutting

Item Verdict Justification
Per-piece template variant across all types = the View layer above One feature, stated twice. Counts as its second concrete use
Alt text and content warnings first-class across types ? "First-class" = enforced per type = declared content types, queue 7, whose trigger is currently "a dated bundle needing to stay out of a feed". Your requirement is a better trigger for it than the recorded one

What this adds up to

Already shipping, or shipping with a theme fragment you write: the majority. Notably the whole admonitions/tabs/panels family, extras folders, includes, series, tags, feeds, sitemap, canonical and redirects, responsive images, code highlighting with line ranges, abbreviations, TOC, dev server, checks, and — verified this session — user-defined shortcodes with no rebuild.

Three items are disproportionately valuable:

  1. Per-piece template variants — earns the View layer and closes Arc 2. Architecturally the most important thing in the list, and you asked for it twice without naming it.
  2. Raw passthrough routes — one small feature, four list entries, and a real gap today.
  3. Corrections/updates per post — no engine code at all, and the one item here that changes whether the writing can be trusted.

Four collide with recorded decisions and are surfaced rather than settled: task lists (ADR-0058), private/secret-link (ADR-0024), git sync (content-model.md), external fetching for oEmbed and static copies (same). One reframe removes the fourth entirely.

Five need JS on ordinary pages, against your own antifeature: copy-to-clipboard, Cmd+K, draggable before/after, lightbox, live reload. Each has a no-JS equivalent except the clipboard.

The shortest line is the biggest job. "Search" is one word and is arc-sized, because Bengali tokenisation is the novel problem this project has been pointing at from the start.