record tags as built: ADR-0032
The queue said to re-adopt the taxonomy decision when tags landed and I did not, so ideas/deferred-decisions.md claimed no tag pages existed while /tags/ had been serving for two commits. ADR-0032 records what the code actually does; only the feed half stays deferred, and it lands with declared types since feed membership is part of a type declaration. Folded from a separate state commit: state: bump verified-against; narrow the declared-types trigger Sequences do not need a type declaration — membership and ordering come from frontmatter — so the trigger for declared types is feeds or check, whichever lands first.
This commit is contained in:
@@ -367,3 +367,20 @@ Consequence: cheap — the guard cannot be forgotten, and the test is one symlin
|
||||
go through the root handle, so no helper may take a `string` path and open it directly, and the root is
|
||||
held for the life of the process.
|
||||
Revisit if: never. A hand-rolled cleaner is strictly worse.
|
||||
|
||||
## ADR-0032 — Tags: one global namespace, grouped in the listing
|
||||
Date: 2026-07-30 · Status: accepted (the tag half of withdrawn ADR-0018, now built; the feed half is still
|
||||
deferred in `ideas/deferred-decisions.md`)
|
||||
Decision: `tags` is one global namespace across every section. `/tags/{term}/` lists everything carrying a
|
||||
term, `/{section}/tags/{term}/` narrows it, and listings group by section. The URL form of a term is
|
||||
lowercased with whitespace hyphenated, preserving script, so case is not a distinction and Bengali passes
|
||||
through unchanged. Structural metadata with a fixed term set — `series` and its kin — is not a tag.
|
||||
Why: cross-type discovery is the point of a single-author site; one term spanning a comic, a poem and a
|
||||
photo essay is the feature, not the noise. Per-section pools would fragment that to solve a readability
|
||||
problem the View solves by grouping. And a free-form cross-cutting tag behaves nothing like a fixed term
|
||||
set that drives engine behaviour, so conflating them makes both worse.
|
||||
Consequence: cheap — one Query with an optional section predicate serves both listings, and the second
|
||||
caller is what earned `Query.Tag` rather than a guess. Expensive — tag hygiene is the author's discipline
|
||||
since nothing scopes terms, so `check` owes a near-duplicate report; and `tags` is now reserved at the top
|
||||
level and inside every section.
|
||||
Revisit if: the pool becomes unusable in practice — and then the answer is curation, not namespacing.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
# State
|
||||
|
||||
**Verified against:** `449850c` on 2026-07-30 — update this line every change.
|
||||
**Verified against:** `fbf24f7` on 2026-07-30 — update this line every change.
|
||||
If this file disagrees with the code, the code is right and this file is a bug.
|
||||
|
||||
## Inventory
|
||||
|
||||
@@ -76,26 +76,13 @@ sets a policy once for everything beneath it. Expensive — resolution must be c
|
||||
runs per bundle, and the set of cascadable keys must stay declared or it becomes unbounded config.
|
||||
Revisit if: cascade resolution shows up in a render-path profile.
|
||||
|
||||
## Taxonomies and feed shape
|
||||
## Feed shape
|
||||
|
||||
Deferred because no tag pages and no feeds in the MVP.
|
||||
Deferred because no feeds exist yet. The tag half of this became ADR-0032 when tags were built.
|
||||
|
||||
## Global flat tags, declared structural taxonomies
|
||||
Date: 2026-07-28 · Status: accepted
|
||||
Decision: `tags` is one global namespace across every type — `/tags/{tag}/` lists everything carrying it,
|
||||
`/{section}/tags/{tag}/` narrows to a section, and listing views group results by type. Structural
|
||||
metadata with known terms that drives behaviour — `series`, `medium`, `genre` — is a *declared* taxonomy
|
||||
on the type (ADR-0014) and never enters the tag pool. Feeds follow the same shape: `/feed.xml` carries
|
||||
every type declared `primary`, `/{section}/feed.xml` carries a section, `/tags/{tag}/feed.xml` falls out
|
||||
of the same Query.
|
||||
Why: cross-type discovery is the point of a single-author site — one tag spanning a comic, a poem and a
|
||||
photo essay is a feature. Per-section tag pools would fragment that for a readability problem better
|
||||
solved by grouping in the View. But a tag is free-form and cross-cutting, while a structural taxonomy has
|
||||
a fixed term set and changes what the engine does; conflating them makes both worse.
|
||||
Consequence: cheap — one Query with an optional section predicate serves tag pages, section tag pages and
|
||||
their feeds. Expensive — tag hygiene is now the author's discipline, since nothing scopes them; the
|
||||
content `check` command should report near-duplicate terms.
|
||||
Revisit if: the tag pool becomes unusable in practice — and then the answer is curation, not namespacing.
|
||||
Recorded direction: `/feed.xml` carries every type declared `primary`, `/{section}/feed.xml` carries a
|
||||
section, and `/tags/{term}/feed.xml` falls out of the same Query. Which types are `primary` is part of the
|
||||
type declaration, so this and declared types land together.
|
||||
|
||||
## Extras
|
||||
|
||||
|
||||
Reference in New Issue
Block a user