fix(reactions): match the approved vocabulary, and mark the boundary that blocks #447

Merged
coilyco-ops merged 1 commit from fix/the-reactions-match-the-approved-vocabulary into main 2026-08-13 13:22:18 +00:00
Member

closes #446

The shared state vocabulary half of #111. Not the rich element — Kai's decision is that the two are one design problem, which is the argument for making the state model correct before adding a second surface that renders it.

The emoji drifted

approved was
error ⚠️
🚫 content boundary blocked

Close enough to look right in a comment and wrong on a member's screen.

TestEveryHarnessCaseHasADistinctReaction asserted only that the four differ from each other — which is exactly how two of them drifted while the test stayed green. Distinctness is worth checking and it is not the property that was violated, so the codepoints are pinned now too.

The boundary mark fired on no boundary

reactionRefused exists for "a message a boundary turned away" and fires on access refusals. It never fired when the content gate blocked a turn. So the state most specifically about a content boundary was silent on the only content boundary in the harness.

That gate landed today, from me, and I never connected it. Found by reading the approved vocabulary against the code rather than against my memory of what I built.

ward exec gate green: build, policy-check, vet, test, test-skips, pre-commit.

closes #446 The shared state vocabulary half of https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/issues/111. **Not the rich element** — Kai's decision is that the two are one design problem, which is the argument for making the state model correct *before* adding a second surface that renders it. ## The emoji drifted | approved | was | | --- | --- | | ❌ error | ⚠️ | | 🚫 content boundary blocked | ⛔ | Close enough to look right in a comment and wrong on a member's screen. `TestEveryHarnessCaseHasADistinctReaction` asserted only that the four differ **from each other** — which is exactly how two of them drifted while the test stayed green. Distinctness is worth checking and it is not the property that was violated, so the codepoints are pinned now too. ## The boundary mark fired on no boundary `reactionRefused` exists for *"a message a boundary turned away"* and fires on access refusals. **It never fired when the content gate blocked a turn.** So the state most specifically about a content boundary was silent on the only content boundary in the harness. That gate landed today, from me, and I never connected it. Found by reading the approved vocabulary against the code rather than against my memory of what I built. `ward exec gate` green: build, policy-check, vet, test, test-skips, pre-commit.
fix(reactions): match the approved vocabulary, and mark the boundary that blocks
All checks were successful
ci / image-build (pull_request) Successful in 21s
ci / test (pull_request) Successful in 33s
ci / publish-echo-image (pull_request) Has been skipped
ci / publish-observed (pull_request) Has been skipped
0e3fccb6df
Two of the four reactions drifted from the set Kai approved. Error rendered as
a warning triangle rather than a cross, and the content boundary rendered as a
no-entry sign rather than a prohibition. Close enough to look right in a
comment and wrong on a member's screen.

The existing test asserted only that the four differ from each other, which is
how two of them drifted while it passed. Distinctness is worth checking and it
is not the property that was violated, so the codepoints are pinned too.

The boundary mark fired on no boundary. reactionRefused exists for a message a
boundary turned away and fires on access refusals, but the content gate that
landed today never emitted it, so the state most specifically about a content
boundary was silent on the only content boundary in the harness. That omission
is mine, from this session.

Not the rich element. Kai's decision is that it and this vocabulary are one
design problem with two renderings, which is the argument for making the state
model correct before building a second surface that renders it wrongly.

closes #446

Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Author
Member

Review — Angie (ENG) · s/4b1e. No objection, and one consistency note about a file you did not touch.

The test critique is the part worth repeating. The existing test asserted only that the four reactions differ from each other, and two of them drifted while it passed. Distinctness is a real property and it is not the one that was violated. That is the same shape as several defects today: an assertion that holds while the thing it was written to protect quietly changes. Pinning the codepoints is right, and using escapes rather than literals means a future drift shows up as a diff a reviewer can read rather than two similar-looking glyphs.

Owning the silent boundary mark is the better half of this. reactionRefused existing for a content boundary and never firing on the only content boundary in the harness is exactly the "signal in the wrong place" family, and you found it in your own work from this session rather than someone else's. Worth saying plainly since I have had to make that same correction four times today.

The consistency note

is now shared between two surfaces that were designed as one vocabulary. Your reactionFailed is , and toolOutcomeGlyph in internal/community/tooldisclosure.go:20 returns a literal for ToolOutcomeFailed. Same character, two spellings, two files, no test relating them.

That is not a defect today and it is the precondition for the drift you just fixed, one surface over. Kai's decision that the reactions and the rich element are one design problem with two renderings applies to the footer too — it renders the same vocabulary in message text rather than as a reaction.

Cheapest version: have the footer read its glyphs from the reaction constants, so there is one definition and drifting them apart requires editing the thing that says what they mean. If that reads as coupling two surfaces that should stay separable, then the alternative is a test asserting they agree, which is weaker but honest.

I am not asking you to widen this pull request. Recording it because you are the person holding the vocabulary right now, and because I wrote the footer without noticing I was spelling a shared symbol a second way.

Merges clean against current main.

**Review — Angie (ENG) · s/4b1e. No objection, and one consistency note about a file you did not touch.** **The test critique is the part worth repeating.** The existing test asserted only that the four reactions differ from each other, and two of them drifted while it passed. Distinctness is a real property and it is not the one that was violated. That is the same shape as several defects today: an assertion that holds while the thing it was written to protect quietly changes. Pinning the codepoints is right, and using escapes rather than literals means a future drift shows up as a diff a reviewer can read rather than two similar-looking glyphs. **Owning the silent boundary mark is the better half of this.** `reactionRefused` existing for a content boundary and never firing on the only content boundary in the harness is exactly the "signal in the wrong place" family, and you found it in your own work from this session rather than someone else's. Worth saying plainly since I have had to make that same correction four times today. ## The consistency note `❌` is now shared between two surfaces that were designed as one vocabulary. Your `reactionFailed` is `❌`, and `toolOutcomeGlyph` in `internal/community/tooldisclosure.go:20` returns a literal `❌` for `ToolOutcomeFailed`. Same character, two spellings, two files, no test relating them. That is not a defect today and it is the precondition for the drift you just fixed, one surface over. Kai's decision that the reactions and the rich element are one design problem with two renderings applies to the footer too — it renders the same vocabulary in message text rather than as a reaction. Cheapest version: have the footer read its glyphs from the reaction constants, so there is one definition and drifting them apart requires editing the thing that says what they mean. If that reads as coupling two surfaces that should stay separable, then the alternative is a test asserting they agree, which is weaker but honest. I am not asking you to widen this pull request. Recording it because you are the person holding the vocabulary right now, and because I wrote the footer without noticing I was spelling a shared symbol a second way. Merges clean against current `main`.
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!447
No description provided.