fix(mentions): a code span is not prose either #496

Merged
coilyco-ops merged 1 commit from eng/code-spans-are-not-prose into main 2026-08-13 14:32:16 +00:00
Member

Third construct in the same class, and the last one I can find a demonstrated harm for.

Inline spans, multi-backtick spans and fenced blocks join links and Discord markup in opaqueSpan. The fence alternative is listed before the inline ones so a fence is not read as an empty inline span followed by loose text.

On the design question

Quail asked whether the right shape, after three of these, is an allowlist of prose rather than a list of excluded spans, and expected the former. I kept the exclusion list, and the doc now records why in two sentences rather than leaving it as an accident of history.

The two shapes fail in opposite directions. An exclusion list fails loudly: an unlisted construct gets rewritten, a member sees a mangled artefact, and it gets filed — which is how all three of these surfaced inside one day. An allowlist fails silently: an unlisted construct stops resolving, a member who should have been reached is not, and the reply reads fine to everyone.

The sets are also different sizes. What carries a payload that is not a person is short and nearly closed: links, code, angle-bracket constructs. What carries prose is not: bold, italic, underline, strikethrough, spoilers, blockquotes, headers, list items, plain text — and a name in any of those is a real reference.

So the doc states one rule now — resolution runs on prose only, these runs are not prose — instead of three bullets that each look like a patch.

Considered and not added

Discord timestamps, <t:1699999999:R>, are not covered by the markup pattern. The payload is digits plus a single letter and the roster refuses names under three runes, so no name can collide. Adding a guard that cannot fire is what the battery doctrine warns against, and I would rather leave it out than carry a check that can only ever pass.

Tests

The corpus plus Quail's exact footer shape, asserting the reply is byte-identical and that nobody was reached — the ping is the harm that survives a cosmetic fix.

Mutating the exclusion to a pattern that matches nothing turns both corpus tests red and leaves the existing link and markup tests green, so they measure the new span type specifically. My first attempt at that mutation silently failed to apply and the suite stayed green; I caught it by checking the line rather than trusting the exit code, and re-ran it properly.

closes #486

Third construct in the same class, and the last one I can find a demonstrated harm for. Inline spans, multi-backtick spans and fenced blocks join links and Discord markup in `opaqueSpan`. The fence alternative is listed before the inline ones so a fence is not read as an empty inline span followed by loose text. ## On the design question Quail asked whether the right shape, after three of these, is an allowlist of prose rather than a list of excluded spans, and expected the former. I kept the exclusion list, and the doc now records why in two sentences rather than leaving it as an accident of history. The two shapes fail in opposite directions. An exclusion list fails **loudly**: an unlisted construct gets rewritten, a member sees a mangled artefact, and it gets filed — which is how all three of these surfaced inside one day. An allowlist fails **silently**: an unlisted construct stops resolving, a member who should have been reached is not, and the reply reads fine to everyone. The sets are also different sizes. What carries a payload that is not a person is short and nearly closed: links, code, angle-bracket constructs. What carries prose is not: bold, italic, underline, strikethrough, spoilers, blockquotes, headers, list items, plain text — and a name in any of those is a real reference. So the doc states one rule now — resolution runs on prose only, these runs are not prose — instead of three bullets that each look like a patch. ## Considered and not added Discord timestamps, `<t:1699999999:R>`, are not covered by the markup pattern. The payload is digits plus a single letter and the roster refuses names under three runes, so no name can collide. Adding a guard that cannot fire is what the battery doctrine warns against, and I would rather leave it out than carry a check that can only ever pass. ## Tests The corpus plus Quail's exact footer shape, asserting the reply is byte-identical **and** that nobody was reached — the ping is the harm that survives a cosmetic fix. Mutating the exclusion to a pattern that matches nothing turns both corpus tests red and leaves the existing link and markup tests green, so they measure the new span type specifically. My first attempt at that mutation silently failed to apply and the suite stayed green; I caught it by checking the line rather than trusting the exit code, and re-ran it properly. closes #486
fix(mentions): a code span is not prose either
All checks were successful
ci / image-build (pull_request) Successful in 22s
ci / test (pull_request) Successful in 36s
ci / publish-echo-image (pull_request) Has been skipped
ci / publish-observed (pull_request) Has been skipped
5ccdb43b05
The disclosure footer is made of backticked tool names, and tool names
are short lowercase words, which is the shape a display name takes. A
member called eco turned the first footer line into a person and left the
second naming the tool, so the receipt contradicted itself and pinged
someone who was never mentioned.

Inline, multi-backtick and fenced spans join links and Discord markup as
runs no name is read inside. The doc now states that as one rule, because
this is the third construct rather than the third special case.

The exclusion list stays an exclusion list. An unlisted markup kind is
rewritten and gets reported; an unlisted prose kind would silently stop
reaching people.

Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-gaming/sirens-echo!496
No description provided.