{"blyg":"0.3","id":"0v96x743shpy68yjamqdxrnaxk","kind":"thread","origin":"https://blyg.blygger.org/","page":"t/0v96x743shpy68yjamqdxrnaxk/","author":{"name":"Venkatesh Rao","url":"https://blyg.blygger.org/"},"created":"2026-10-07T20:03:11Z","updated":"2026-10-07T20:03:11Z","version":1,"content_md":"\n# TN-3 — Groups need no new construct: N origins, one masthead, and the stubbing anti-pattern\n\n**Technical note · non-normative · session 28, 2026-09-28 (Opus 5, writing up\ndecision #36 — ruled session 27 by Fable + Venkat). Decision record for locked\ndecision #36.** Technical notes record design reasoning — especially rejected\ndesigns — alongside the normative spec; they constrain nothing and are citable\nrationale, not protocol. Written against protocol 0.3 as published on\n2026-09-28; every construct named here is built and live, but no pre-1.0\nversion promises anything (#21), so check the living text before you lean on a\ndetail.\n\n**Revised session 38, 2026-10-06 (Opus 5.5)**, after decision #61: §3 gains the\nconsequence that members on one host cannot verify mentions in each other's\nname, which was not true of the 0.3 text this note was first written against.\n\n## 1. The question\n\nTwo requests arrived from early users within days of the first strangers\nstanding up their own blygs:\n\n1. **\"A multi-user blyg with separate folders.\"** A publication or workgroup\n   wants several people writing under one roof, each with their own space.\n2. **\"An aggregator that stubs everything.\"** A site wants to be the one place\n   to follow a group, and proposed doing it by emitting a stub for every item\n   the members publish.\n\nBoth read like requests for a new construct — a group, a space, a members\nlist, a pipe. Neither is. The first decomposes into two shapes the protocol\nalready has, distinguished by one question; the second is an anti-pattern, and\nthe interesting part is *why* it cannot be stopped by a rule.\n\nThe spec's own involvement in all of this is two sentences of documentation: a\nwarning in §10.6 and the honest shape named in §13.5. This note is the\nreasoning behind those sentences.\n\n## 2. There is no folder on the wire\n\nStart with what \"separate folders\" would have to mean. A blyg is a directory of\nfiles under an origin: one `blyg.json`, one `feed.xml`, one `items/index.json`,\nand item documents (spec §4). Every reference in the protocol — `transclusions[]`,\n`stub_of`, `forked_from` — names `{origin, id, version}` (§5.9). Subscription\ntargets an origin (§12.2). Withdrawal is an act by an origin about its own item\n(spec §9). Pins are hosting promises made by an origin (spec §8).\n\nNothing in that list has a place to put a folder, and adding one would mean\nadding an addressable sub-identity beneath the origin — which is exactly what\n#11 refuses (\"authors are never addressable … permanently\") and what invariant\n4 refuses one level up (\"the only authenticated entity is the publishing client\nat its domain\").\n\nSo the folder, if it exists, is a **studio view**: a way of organising the\nauthoring tool, invisible on the page, which is precisely where #1's\nstudio/page split puts it. Members in the studio are #31's scoped bearer\ntokens — owner-minted, owner-revoked, per-client, with coarse verb scopes. A\nmember is a token with a member's scopes, and the wire never learns that any of\nthis happened.\n\nWhat the request actually asks, once the folder is set aside, is: **how many\norigins?** There are two answers, and they are different protocols of trust,\nnot different implementations of one.\n\n## 3. Shape A — N origins under one host\n\nMount independence (#14) means a blyg's origin is *any* absolute base URL, and\nno protocol construct may infer anything from the path. So one host serves as\nmany blygs as it likes:\n\n```\nhttps://house.example/alice/     blyg.json, feed.xml, items/…\nhttps://house.example/bob/       blyg.json, feed.xml, items/…\nhttps://house.example/           the house's own blyg (optional)\n```\n\nSubdomains work identically (`alice.house.example`) and were exercised in the\nwild by a stranger who path-mounted at `/blyg/` without being told it was\nallowed.\n\n**The index is a blogroll.** The house publishes `blogroll.opml` (§11) listing\nits members. A reader importing that one OPML file subscribes to every member\nat once — and nothing custom was needed to make that work, because each\nmember's feed carries `<blyg:manifest>`, so plain OPML resolves to the blyg\nupgrade for free (§11, #13, #17). The members list a group construct would have\nintroduced already exists, in a format other people's tooling reads, published\nas a deliberate curated act with no completeness claim.\n\n**Optionally a house blyg.** The house origin can be a blyg of its own, and if\nthe house has an editorial voice it should be: editorials, announcements,\ncurated hoppers of member work (§13.5), stubs that actually respond to\nmembers' pieces. The house is then a publisher among publishers, with its own\naccountability, rather than a directory pretending to be a publication.\n\nConsequences worth naming before choosing this shape:\n\n- Each member withdraws their own items (spec §9) and owns their own pins (spec §8).\n- Each member's `author` is their own assertion at their own origin.\n- Cross-member quoting is ordinary cross-client transclusion (#26) and sends\n  real Webmentions (§15). The house's internal conversation is publicly\n  checkable exactly like anybody else's — a feature, not overhead.\n- **Members cannot speak in each other's name.** A mention verifies only if\n  the source's item document was fetched from exactly `{origin}items/{id}.json`\n  for the origin it declares (§15.4 step 2, decision #61). So a document\n  served under `house.example/alice/` that claims to be `house.example/bob/`\n  fails, and Bob's items are safe from Alice even though they share a host.\n  This was not true when this note was first written: the 0.3 text compared\n  scheme, host and port only, and Aneesh Sathe's conformance model found the\n  hole in exactly this shape (finding F1). The eighth revision of the spec\n  closed it on 2026-10-06, and blygger-studio 0.32.2 implements it. A receiver\n  still running older code keeps the hole until it upgrades, so a house on a\n  shared host should run current clients for all its members.\n- The cost is real: N deploys, N polling crons, N sets of pin promises, N\n  archives to keep serving forever. Withdrawal being permanent and pins being\n  irrevocable means an origin is a long commitment, and this shape makes N of\n  them.\n\n## 4. Shape B — one origin with bylines\n\nThe masthead, specified since #11: one origin, one feed, one archive index, one\nmanifest, and per-item `author` bylines. The feed invariant is\nsingle-**publisher**, never single-author (§5.5), precisely so that this shape\nis conformant without a social layer.\n\nConsequences, which are the mirror image of shape A's:\n\n- The publisher can withdraw anyone's item and owns every pin. One party is\n  accountable for everything at that origin, which is the point.\n- No member has a citation surface of their own. A stub of Alice's piece is a\n  stub of the house's item, carrying Alice's byline as passed-through data.\n- One subscription, one blogroll, one editorial identity, one deploy, one cron.\n- A member's items cannot leave with them. Ids are origin-scoped (#2, §5.1);\n  the same words at a new origin are a new item, or a fork from a pin (§5.6).\n\n## 5. The test: who can withdraw\n\n#36 names one question to choose between the shapes, and it is not \"how many\npeople are there\":\n\n> **Can this person's accountability be someone else's?**\n\nOperationally: **who gets to withdraw, and who owns the pins.** Withdrawal is\nthe protocol's only exit and it is permanent (#8); a pin is an irrevocable\npromise to serve one version forever. Those two are the whole of what an origin\nis on the hook for. A member whose retractions must be their own decision, and\nwhose citations must survive a falling-out with the house, needs their own\norigin. A member who is content for the house to answer for their work does\nnot.\n\nThis cuts across the intuitive axis. A five-person magazine with a real editor\nis one origin — the editor withdrawing a piece *is* the editorial relationship\nworking. Two friends who trust each other completely but publish under\nprofessionally distinct names need two origins, because the thing they need\nseparate is not affection but accountability.\n\n**The choice is less fateful than it looks, because of #35.** Practice for\nidentity (proposed in `docs/proposals/identity-practice-proposal.md`) is that a\nperson is a URL they control, provable by a reciprocal link or a signature. A\nbyline carrying a verified home URL is recognisable after a move from shape B\nto shape A, which is otherwise impossible: §5.5 forbids treating equal `author`\nvalues at different origins as the same entity, and a verified claim is the\nonly thing that lifts it. Be precise about what is portable, because this is\nwhere an implementer will over-promise: **the person is portable, the items are\nnot.** Moving means new ids at a new origin, with lineage expressed as forks\nfrom pins if the old origin pinned anything.\n\n## 6. Why content-free stubbing is an anti-pattern\n\nThe aggregator-by-stub proposal is the interesting half, because the pipe it\ndescribes is *byte-for-byte conformant*. Every document it emits is a valid\nthread with a valid `stub_of` (§10.6). Every mention it sends passes structural\nverification (§15.4). No rule in the spec is broken. It is still wrong, for\nthree independent reasons, and then there is the question of why the spec\nresponds with prose instead of a MUST NOT.\n\n### 6.1 The marker is the one claim nothing can check\n\n`stub_of` is the protocol's only machine-readable assertion that *this is a\nresponse to that*. §10.6 rule 2 makes readers rely on the marker and never on\nbody inspection — deliberately, because inspecting a body to decide whether it\nis a response would require the protocol to read prose, and it would let a\nreader overrule an author about what they wrote.\n\nThat design puts the marker's entire value in its honesty. Structural\nverification does not help: §15.4 checks that the source document really names\nthe target at the origin it claims — it proves the *relation exists*, never\nthat the relation *means* anything. A pipe satisfies it perfectly. So a stub\nemitted with nothing to say is not a weak response; it is a false statement in\nthe one field where the protocol has no defence but truthfulness.\n\n### 6.2 It floods the only scarce inbound signal there is\n\nThe protocol has no follower list, no follower count, no metrics, at any level,\never (#12, #13, §11). A publisher's entire inbound signal is verified mentions\n(§15.5) — and #41 identifies it as the strongest discovery signal available,\nbecause someone who responded to you demonstrably read you.\n\nThat signal is scarce by construction, which is what makes it informative.\nPipe-generated stubs are indistinguishable from real ones at the receiver — the\nreceiver sees a valid thread with a valid marker — so they degrade the signal to\nnoise with no filter available, and the noise is loudest for exactly the\npublishers a group aggregator would target.\n\nThis is the trackback failure reproduced inside the protocol.\nTrackback died of unverified spam, and the protocol answered it with structural\nverification (#13). Verification defeats the *impostor*, who claims a relation\nthat isn't in the document. It does nothing about the *relay*, whose relation\nis genuinely there and genuinely empty.\n\n### 6.3 It reprices re-emission to zero, which §13.5 forbids by cost\n\n§13.5's ban on re-emitting imported items has two halves with two different\nenforcement mechanisms. The mechanical half — imported items MUST NOT appear in\nyour feed, index, or item documents — is enforced by the `blyg:id` rollup\ncontract and the single-publisher invariant: violating it breaks readers, so it\nholds itself up. The editorial half — \"speech about someone else's content\ncosts editorial work\" (#12) — is enforced by *nothing but the cost*. Write an\nitem; that is the price.\n\nAutomating stub creation sets that price to zero. The result is the naked\nretweet that #12 refused, rebuilt out of legal parts: content appears on your\nfeed under your origin with no editorial act anywhere in the loop. Nothing\nmechanical catches it, because there is nothing mechanically different to\ncatch.\n\n### 6.4 The line is content-free, not automated, and not non-human\n\nThis must be said explicitly, because the obvious summary of sections 6.1–6.3 above is \"don't\nlet robots stub\", and that summary is wrong. #38 rules the protocol\nagent-agnostic at every level: an agent is a valid `author` (§5.5), generated\nprose is disclosed by `generated` (§5.7), and invariant 3 constrains the reader\nside and the wire, never who writes.\n\nAn agent that reads each member item and answers it under its own byline,\ndisclosed as generated, is **stubbing legitimately, however many stubs that\nis** — a critic, not a planet. Many mentions from one busy respondent are fine;\neach one says a real thing about a real item (#44 makes the same point for\ngeneration sources). What is illegitimate is a response with nothing in it,\nwhoever or whatever emits it. A human who copy-pastes \"interesting\" under fifty\ntransclusions a day has built the same pipe by hand.\n\n### 6.5 Why this is a warning sentence and not a MUST NOT\n\nThe natural instinct is to forbid it: \"a stub MUST carry editorial content.\"\nThat rule cannot be written, for two reasons.\n\n**It is not checkable.** \"Has something to say\" has no machine test. A word\ncount is trivially defeated and would fail legitimate one-line responses. A\nsimilarity check against the target is an editorial judgement the protocol has\nno business making. A MUST that nothing can test is worse than no MUST: it\nteaches implementers that this spec's requirements are aspirational, which\ndevalues the ones that are real. #48's conformance partition depends on\nMUST-clauses being exactly the set a checker fails on.\n\n**The constructs are identical.** A pipe's output and a critic's output differ\nonly in what the prose says. There is no field, count, flag, or shape that\nseparates them — which is the same reason #38 refuses an \"I am an agent\" flag\n(a spammer would not set it) and #34 refuses a maintenance declaration (the\nsoftware that would have to say it is the software nobody updates).\n\nSo the spec does the only thing available: it says plainly, in §10.6, that a\nstub emitted without a response is a misuse, names the honest alternative in\nthe same breath, and leaves it as reputation rather than validation. A protocol\nthat cannot enforce a norm can still refuse to pretend the norm doesn't exist.\n\n## 7. The honest aggregator, which needs nothing new\n\nEverything the \"one place to follow a group\" request actually wants is already\nbuilt:\n\n1. **Curation display** (§13.5). Import the members, display their items\n   publicly with source attribution and links to the origin. Publicity is a\n   property of the displayed list, never of an imported item — there is no\n   per-item public toggle and there will not be, because that is the naked\n   retweet again.\n2. **A blogroll of the members** (§11). One OPML import subscribes a reader to\n   every member. This is the aggregator's most valuable output: it makes itself\n   unnecessary for readers who have a blyg-aware client, which is the correct\n   relationship for a directory to have with the medium it indexes.\n3. **Optionally a plain RSS digest, outside the blyg surface** (§13.5).\n   Excerpts and links to origin permalinks, no `blyg:` namespace, not\n   `feed.xml`. Its consumers are L0 readers who need nothing from the protocol, and\n   keeping it outside the surface is what stops it being re-emission.\n4. **Optionally its own blyg**, if it has an editorial voice — see section 3 above. A\n   digest is plumbing; an editorial voice is a publisher, and a publisher's\n   stubs are real responses.\n\nNo re-emission at any step, and no stubs on the members' behalf.\n\n## 8. Rejected designs\n\nRecorded because each will be re-proposed.\n\n1. **A group or space construct** — a `members` array in the manifest, a\n   `group` key, a shared parent identity. Rejected three ways: it is a\n   follower-list-shaped surface and the first place a count could attach\n   (#12/#13, and #47 refused a per-item responses list for the same reason);\n   it makes something below the origin addressable, which #11 forbids\n   permanently; and it duplicates the blogroll, which is already the members\n   list, already curated, already read by other people's tooling.\n2. **`user@server` or any two-level addressing.** Closed at #11: DNS is the\n   namespace. Mount independence is what makes the second level unnecessary —\n   a path *is* a namespace, and `house.example/alice/` is a first-class origin\n   with no new grammar.\n3. **Per-author feeds carved out of one origin** (`feed.xml?author=alice`).\n   The feed URL is bound up with subscription identity (§12.2), and the\n   manifest's `feed` value is what locates it (#51). A per-member feed with its\n   own manifest is not a variant of shape B; it *is* shape A, with the\n   deployment cost hidden until the first withdrawal.\n4. **Letting an aggregator re-emit member items.** Not a policy call but a\n   collision: `blyg:id` rollup plus the single-publisher invariant means the\n   copy and the original present as one item with two publishers (§13.5).\n5. **A digest construct on the wire.** Unnecessary — the digest's audience is\n   plain RSS readers, so it needs no blyg vocabulary, and giving it some would\n   put a second lossy notification plane inside a surface that already has one.\n6. **The aggregator-by-stub pipe**, per section 6 above.\n\n## 9. What stands\n\n- **No new construct for groups, at any level.** Two supported shapes: N\n  origins under one host with a house blogroll (and optionally a house blyg),\n  or one origin with per-item bylines.\n- **The test is who can withdraw** — accountability, not headcount. #35's\n  verified home URL is what keeps a byline recognisable if the answer changes\n  later; the person moves, the items do not.\n- **Members are studio-side**, as #31's scoped tokens. There are no author\n  folders on the wire: one origin, one feed, one index, and the byline is the\n  distinction.\n- **A stub emitted without a response is a misuse** — false in the one field\n  nothing can verify, a flood of the only scarce inbound signal, and a\n  repricing of re-emission to zero. Said as a warning in §10.6 rather than a\n  rule, because no rule can distinguish the pipe from the critic, and an\n  unenforceable MUST would cost more than it bought.\n- **The honest aggregator is §13.5 plus §11**, plus a plain RSS digest outside\n  the surface if it wants one. This is locked decision #36; relitigating it\n  starts from this note.\n\n\n\n*This note's canonical text is at [blygger.org/notes/tn-3/](https://blygger.org/notes/tn-3/), and its source is [`docs/notes/tn-3-groups-and-aggregation.md`](https://github.com/blygger/blygger-spec/blob/main/docs/notes/tn-3-groups-and-aggregation.md) in blygger-spec. The page there is what the spec cites. To comment, respond to this item from your own blyg.*\n\n","content_html":"<div class=\"blyg-tk-gen\"><h1>TN-3 — Groups need no new construct: N origins, one masthead, and the stubbing anti-pattern</h1>\n<p><strong>Technical note · non-normative · session 28, 2026-09-28 (Opus 5, writing up\ndecision #36 — ruled session 27 by Fable + Venkat). Decision record for locked\ndecision #36.</strong> Technical notes record design reasoning — especially rejected\ndesigns — alongside the normative spec; they constrain nothing and are citable\nrationale, not protocol. Written against protocol 0.3 as published on\n2026-09-28; every construct named here is built and live, but no pre-1.0\nversion promises anything (#21), so check the living text before you lean on a\ndetail.</p>\n<p><strong>Revised session 38, 2026-10-06 (Opus 5.5)</strong>, after decision #61: §3 gains the\nconsequence that members on one host cannot verify mentions in each other's\nname, which was not true of the 0.3 text this note was first written against.</p>\n<h2>1. The question</h2>\n<p>Two requests arrived from early users within days of the first strangers\nstanding up their own blygs:</p>\n<ol>\n<li><strong>&quot;A multi-user blyg with separate folders.&quot;</strong> A publication or workgroup\nwants several people writing under one roof, each with their own space.</li>\n<li><strong>&quot;An aggregator that stubs everything.&quot;</strong> A site wants to be the one place\nto follow a group, and proposed doing it by emitting a stub for every item\nthe members publish.</li>\n</ol>\n<p>Both read like requests for a new construct — a group, a space, a members\nlist, a pipe. Neither is. The first decomposes into two shapes the protocol\nalready has, distinguished by one question; the second is an anti-pattern, and\nthe interesting part is <em>why</em> it cannot be stopped by a rule.</p>\n<p>The spec's own involvement in all of this is two sentences of documentation: a\nwarning in §10.6 and the honest shape named in §13.5. This note is the\nreasoning behind those sentences.</p>\n<h2>2. There is no folder on the wire</h2>\n<p>Start with what &quot;separate folders&quot; would have to mean. A blyg is a directory of\nfiles under an origin: one <code>blyg.json</code>, one <code>feed.xml</code>, one <code>items/index.json</code>,\nand item documents (spec §4). Every reference in the protocol — <code>transclusions[]</code>,\n<code>stub_of</code>, <code>forked_from</code> — names <code>{origin, id, version}</code> (§5.9). Subscription\ntargets an origin (§12.2). Withdrawal is an act by an origin about its own item\n(spec §9). Pins are hosting promises made by an origin (spec §8).</p>\n<p>Nothing in that list has a place to put a folder, and adding one would mean\nadding an addressable sub-identity beneath the origin — which is exactly what\n#11 refuses (&quot;authors are never addressable … permanently&quot;) and what invariant\n4 refuses one level up (&quot;the only authenticated entity is the publishing client\nat its domain&quot;).</p>\n<p>So the folder, if it exists, is a <strong>studio view</strong>: a way of organising the\nauthoring tool, invisible on the page, which is precisely where #1's\nstudio/page split puts it. Members in the studio are #31's scoped bearer\ntokens — owner-minted, owner-revoked, per-client, with coarse verb scopes. A\nmember is a token with a member's scopes, and the wire never learns that any of\nthis happened.</p>\n<p>What the request actually asks, once the folder is set aside, is: <strong>how many\norigins?</strong> There are two answers, and they are different protocols of trust,\nnot different implementations of one.</p>\n<h2>3. Shape A — N origins under one host</h2>\n<p>Mount independence (#14) means a blyg's origin is <em>any</em> absolute base URL, and\nno protocol construct may infer anything from the path. So one host serves as\nmany blygs as it likes:</p>\n<pre><code>https://house.example/alice/     blyg.json, feed.xml, items/…\nhttps://house.example/bob/       blyg.json, feed.xml, items/…\nhttps://house.example/           the house's own blyg (optional)\n</code></pre>\n<p>Subdomains work identically (<code>alice.house.example</code>) and were exercised in the\nwild by a stranger who path-mounted at <code>/blyg/</code> without being told it was\nallowed.</p>\n<p><strong>The index is a blogroll.</strong> The house publishes <code>blogroll.opml</code> (§11) listing\nits members. A reader importing that one OPML file subscribes to every member\nat once — and nothing custom was needed to make that work, because each\nmember's feed carries <code>&lt;blyg:manifest&gt;</code>, so plain OPML resolves to the blyg\nupgrade for free (§11, #13, #17). The members list a group construct would have\nintroduced already exists, in a format other people's tooling reads, published\nas a deliberate curated act with no completeness claim.</p>\n<p><strong>Optionally a house blyg.</strong> The house origin can be a blyg of its own, and if\nthe house has an editorial voice it should be: editorials, announcements,\ncurated hoppers of member work (§13.5), stubs that actually respond to\nmembers' pieces. The house is then a publisher among publishers, with its own\naccountability, rather than a directory pretending to be a publication.</p>\n<p>Consequences worth naming before choosing this shape:</p>\n<ul>\n<li>Each member withdraws their own items (spec §9) and owns their own pins (spec §8).</li>\n<li>Each member's <code>author</code> is their own assertion at their own origin.</li>\n<li>Cross-member quoting is ordinary cross-client transclusion (#26) and sends\nreal Webmentions (§15). The house's internal conversation is publicly\ncheckable exactly like anybody else's — a feature, not overhead.</li>\n<li><strong>Members cannot speak in each other's name.</strong> A mention verifies only if\nthe source's item document was fetched from exactly <code>{origin}items/{id}.json</code>\nfor the origin it declares (§15.4 step 2, decision #61). So a document\nserved under <code>house.example/alice/</code> that claims to be <code>house.example/bob/</code>\nfails, and Bob's items are safe from Alice even though they share a host.\nThis was not true when this note was first written: the 0.3 text compared\nscheme, host and port only, and Aneesh Sathe's conformance model found the\nhole in exactly this shape (finding F1). The eighth revision of the spec\nclosed it on 2026-10-06, and blygger-studio 0.32.2 implements it. A receiver\nstill running older code keeps the hole until it upgrades, so a house on a\nshared host should run current clients for all its members.</li>\n<li>The cost is real: N deploys, N polling crons, N sets of pin promises, N\narchives to keep serving forever. Withdrawal being permanent and pins being\nirrevocable means an origin is a long commitment, and this shape makes N of\nthem.</li>\n</ul>\n<h2>4. Shape B — one origin with bylines</h2>\n<p>The masthead, specified since #11: one origin, one feed, one archive index, one\nmanifest, and per-item <code>author</code> bylines. The feed invariant is\nsingle-<strong>publisher</strong>, never single-author (§5.5), precisely so that this shape\nis conformant without a social layer.</p>\n<p>Consequences, which are the mirror image of shape A's:</p>\n<ul>\n<li>The publisher can withdraw anyone's item and owns every pin. One party is\naccountable for everything at that origin, which is the point.</li>\n<li>No member has a citation surface of their own. A stub of Alice's piece is a\nstub of the house's item, carrying Alice's byline as passed-through data.</li>\n<li>One subscription, one blogroll, one editorial identity, one deploy, one cron.</li>\n<li>A member's items cannot leave with them. Ids are origin-scoped (#2, §5.1);\nthe same words at a new origin are a new item, or a fork from a pin (§5.6).</li>\n</ul>\n<h2>5. The test: who can withdraw</h2>\n<p>#36 names one question to choose between the shapes, and it is not &quot;how many\npeople are there&quot;:</p>\n<blockquote>\n<p><strong>Can this person's accountability be someone else's?</strong></p>\n</blockquote>\n<p>Operationally: <strong>who gets to withdraw, and who owns the pins.</strong> Withdrawal is\nthe protocol's only exit and it is permanent (#8); a pin is an irrevocable\npromise to serve one version forever. Those two are the whole of what an origin\nis on the hook for. A member whose retractions must be their own decision, and\nwhose citations must survive a falling-out with the house, needs their own\norigin. A member who is content for the house to answer for their work does\nnot.</p>\n<p>This cuts across the intuitive axis. A five-person magazine with a real editor\nis one origin — the editor withdrawing a piece <em>is</em> the editorial relationship\nworking. Two friends who trust each other completely but publish under\nprofessionally distinct names need two origins, because the thing they need\nseparate is not affection but accountability.</p>\n<p><strong>The choice is less fateful than it looks, because of #35.</strong> Practice for\nidentity (proposed in <code>docs/proposals/identity-practice-proposal.md</code>) is that a\nperson is a URL they control, provable by a reciprocal link or a signature. A\nbyline carrying a verified home URL is recognisable after a move from shape B\nto shape A, which is otherwise impossible: §5.5 forbids treating equal <code>author</code>\nvalues at different origins as the same entity, and a verified claim is the\nonly thing that lifts it. Be precise about what is portable, because this is\nwhere an implementer will over-promise: <strong>the person is portable, the items are\nnot.</strong> Moving means new ids at a new origin, with lineage expressed as forks\nfrom pins if the old origin pinned anything.</p>\n<h2>6. Why content-free stubbing is an anti-pattern</h2>\n<p>The aggregator-by-stub proposal is the interesting half, because the pipe it\ndescribes is <em>byte-for-byte conformant</em>. Every document it emits is a valid\nthread with a valid <code>stub_of</code> (§10.6). Every mention it sends passes structural\nverification (§15.4). No rule in the spec is broken. It is still wrong, for\nthree independent reasons, and then there is the question of why the spec\nresponds with prose instead of a MUST NOT.</p>\n<h3>6.1 The marker is the one claim nothing can check</h3>\n<p><code>stub_of</code> is the protocol's only machine-readable assertion that <em>this is a\nresponse to that</em>. §10.6 rule 2 makes readers rely on the marker and never on\nbody inspection — deliberately, because inspecting a body to decide whether it\nis a response would require the protocol to read prose, and it would let a\nreader overrule an author about what they wrote.</p>\n<p>That design puts the marker's entire value in its honesty. Structural\nverification does not help: §15.4 checks that the source document really names\nthe target at the origin it claims — it proves the <em>relation exists</em>, never\nthat the relation <em>means</em> anything. A pipe satisfies it perfectly. So a stub\nemitted with nothing to say is not a weak response; it is a false statement in\nthe one field where the protocol has no defence but truthfulness.</p>\n<h3>6.2 It floods the only scarce inbound signal there is</h3>\n<p>The protocol has no follower list, no follower count, no metrics, at any level,\never (#12, #13, §11). A publisher's entire inbound signal is verified mentions\n(§15.5) — and #41 identifies it as the strongest discovery signal available,\nbecause someone who responded to you demonstrably read you.</p>\n<p>That signal is scarce by construction, which is what makes it informative.\nPipe-generated stubs are indistinguishable from real ones at the receiver — the\nreceiver sees a valid thread with a valid marker — so they degrade the signal to\nnoise with no filter available, and the noise is loudest for exactly the\npublishers a group aggregator would target.</p>\n<p>This is the trackback failure reproduced inside the protocol.\nTrackback died of unverified spam, and the protocol answered it with structural\nverification (#13). Verification defeats the <em>impostor</em>, who claims a relation\nthat isn't in the document. It does nothing about the <em>relay</em>, whose relation\nis genuinely there and genuinely empty.</p>\n<h3>6.3 It reprices re-emission to zero, which §13.5 forbids by cost</h3>\n<p>§13.5's ban on re-emitting imported items has two halves with two different\nenforcement mechanisms. The mechanical half — imported items MUST NOT appear in\nyour feed, index, or item documents — is enforced by the <code>blyg:id</code> rollup\ncontract and the single-publisher invariant: violating it breaks readers, so it\nholds itself up. The editorial half — &quot;speech about someone else's content\ncosts editorial work&quot; (#12) — is enforced by <em>nothing but the cost</em>. Write an\nitem; that is the price.</p>\n<p>Automating stub creation sets that price to zero. The result is the naked\nretweet that #12 refused, rebuilt out of legal parts: content appears on your\nfeed under your origin with no editorial act anywhere in the loop. Nothing\nmechanical catches it, because there is nothing mechanically different to\ncatch.</p>\n<h3>6.4 The line is content-free, not automated, and not non-human</h3>\n<p>This must be said explicitly, because the obvious summary of sections 6.1–6.3 above is &quot;don't\nlet robots stub&quot;, and that summary is wrong. #38 rules the protocol\nagent-agnostic at every level: an agent is a valid <code>author</code> (§5.5), generated\nprose is disclosed by <code>generated</code> (§5.7), and invariant 3 constrains the reader\nside and the wire, never who writes.</p>\n<p>An agent that reads each member item and answers it under its own byline,\ndisclosed as generated, is <strong>stubbing legitimately, however many stubs that\nis</strong> — a critic, not a planet. Many mentions from one busy respondent are fine;\neach one says a real thing about a real item (#44 makes the same point for\ngeneration sources). What is illegitimate is a response with nothing in it,\nwhoever or whatever emits it. A human who copy-pastes &quot;interesting&quot; under fifty\ntransclusions a day has built the same pipe by hand.</p>\n<h3>6.5 Why this is a warning sentence and not a MUST NOT</h3>\n<p>The natural instinct is to forbid it: &quot;a stub MUST carry editorial content.&quot;\nThat rule cannot be written, for two reasons.</p>\n<p><strong>It is not checkable.</strong> &quot;Has something to say&quot; has no machine test. A word\ncount is trivially defeated and would fail legitimate one-line responses. A\nsimilarity check against the target is an editorial judgement the protocol has\nno business making. A MUST that nothing can test is worse than no MUST: it\nteaches implementers that this spec's requirements are aspirational, which\ndevalues the ones that are real. #48's conformance partition depends on\nMUST-clauses being exactly the set a checker fails on.</p>\n<p><strong>The constructs are identical.</strong> A pipe's output and a critic's output differ\nonly in what the prose says. There is no field, count, flag, or shape that\nseparates them — which is the same reason #38 refuses an &quot;I am an agent&quot; flag\n(a spammer would not set it) and #34 refuses a maintenance declaration (the\nsoftware that would have to say it is the software nobody updates).</p>\n<p>So the spec does the only thing available: it says plainly, in §10.6, that a\nstub emitted without a response is a misuse, names the honest alternative in\nthe same breath, and leaves it as reputation rather than validation. A protocol\nthat cannot enforce a norm can still refuse to pretend the norm doesn't exist.</p>\n<h2>7. The honest aggregator, which needs nothing new</h2>\n<p>Everything the &quot;one place to follow a group&quot; request actually wants is already\nbuilt:</p>\n<ol>\n<li><strong>Curation display</strong> (§13.5). Import the members, display their items\npublicly with source attribution and links to the origin. Publicity is a\nproperty of the displayed list, never of an imported item — there is no\nper-item public toggle and there will not be, because that is the naked\nretweet again.</li>\n<li><strong>A blogroll of the members</strong> (§11). One OPML import subscribes a reader to\nevery member. This is the aggregator's most valuable output: it makes itself\nunnecessary for readers who have a blyg-aware client, which is the correct\nrelationship for a directory to have with the medium it indexes.</li>\n<li><strong>Optionally a plain RSS digest, outside the blyg surface</strong> (§13.5).\nExcerpts and links to origin permalinks, no <code>blyg:</code> namespace, not\n<code>feed.xml</code>. Its consumers are L0 readers who need nothing from the protocol, and\nkeeping it outside the surface is what stops it being re-emission.</li>\n<li><strong>Optionally its own blyg</strong>, if it has an editorial voice — see section 3 above. A\ndigest is plumbing; an editorial voice is a publisher, and a publisher's\nstubs are real responses.</li>\n</ol>\n<p>No re-emission at any step, and no stubs on the members' behalf.</p>\n<h2>8. Rejected designs</h2>\n<p>Recorded because each will be re-proposed.</p>\n<ol>\n<li><strong>A group or space construct</strong> — a <code>members</code> array in the manifest, a\n<code>group</code> key, a shared parent identity. Rejected three ways: it is a\nfollower-list-shaped surface and the first place a count could attach\n(#12/#13, and #47 refused a per-item responses list for the same reason);\nit makes something below the origin addressable, which #11 forbids\npermanently; and it duplicates the blogroll, which is already the members\nlist, already curated, already read by other people's tooling.</li>\n<li><strong><code>user@server</code> or any two-level addressing.</strong> Closed at #11: DNS is the\nnamespace. Mount independence is what makes the second level unnecessary —\na path <em>is</em> a namespace, and <code>house.example/alice/</code> is a first-class origin\nwith no new grammar.</li>\n<li><strong>Per-author feeds carved out of one origin</strong> (<code>feed.xml?author=alice</code>).\nThe feed URL is bound up with subscription identity (§12.2), and the\nmanifest's <code>feed</code> value is what locates it (#51). A per-member feed with its\nown manifest is not a variant of shape B; it <em>is</em> shape A, with the\ndeployment cost hidden until the first withdrawal.</li>\n<li><strong>Letting an aggregator re-emit member items.</strong> Not a policy call but a\ncollision: <code>blyg:id</code> rollup plus the single-publisher invariant means the\ncopy and the original present as one item with two publishers (§13.5).</li>\n<li><strong>A digest construct on the wire.</strong> Unnecessary — the digest's audience is\nplain RSS readers, so it needs no blyg vocabulary, and giving it some would\nput a second lossy notification plane inside a surface that already has one.</li>\n<li><strong>The aggregator-by-stub pipe</strong>, per section 6 above.</li>\n</ol>\n<h2>9. What stands</h2>\n<ul>\n<li><strong>No new construct for groups, at any level.</strong> Two supported shapes: N\norigins under one host with a house blogroll (and optionally a house blyg),\nor one origin with per-item bylines.</li>\n<li><strong>The test is who can withdraw</strong> — accountability, not headcount. #35's\nverified home URL is what keeps a byline recognisable if the answer changes\nlater; the person moves, the items do not.</li>\n<li><strong>Members are studio-side</strong>, as #31's scoped tokens. There are no author\nfolders on the wire: one origin, one feed, one index, and the byline is the\ndistinction.</li>\n<li><strong>A stub emitted without a response is a misuse</strong> — false in the one field\nnothing can verify, a flood of the only scarce inbound signal, and a\nrepricing of re-emission to zero. Said as a warning in §10.6 rather than a\nrule, because no rule can distinguish the pipe from the critic, and an\nunenforceable MUST would cost more than it bought.</li>\n<li><strong>The honest aggregator is §13.5 plus §11</strong>, plus a plain RSS digest outside\nthe surface if it wants one. This is locked decision #36; relitigating it\nstarts from this note.</li>\n</ul>\n</div>\n<p><span class=\"blyg-tk-gen\">\n<em>This note's canonical text is at <a href=\"https://blygger.org/notes/tn-3/\">blygger.org/notes/tn-3/</a>, and its source is <a href=\"https://github.com/blygger/blygger-spec/blob/main/docs/notes/tn-3-groups-and-aggregation.md\"><code>docs/notes/tn-3-groups-and-aggregation.md</code></a> in blygger-spec. The page there is what the spec cites. To comment, respond to this item from your own blyg.</em>\n</span></p>\n","content_hash":"sha256:2f63d9a8d3179f896fb53e8f7e647163f5f40267583a374eeac3b7bee700467d","media":[],"transclusions":[],"generated":[{"sources":[],"model":"claude-opus-5"},{"sources":[],"model":"claude-opus-5-5"}],"changelog":[{"version":1,"at":"2026-10-07T20:03:11Z","note":"Ported from blygger.org/notes/tn-3/ (decision #66); the canonical text stays there."}]}