feat: the announcement link, on the card and in a review queue (388 E5)
CI / lint (push) Successful in 4s
CI / extension-version (push) Successful in 3s
Build images / sign-extension (push) Successful in 5s
Build images / build-agent (push) Successful in 8s
Build images / build-ml (push) Successful in 8s
CI / frontend-build (push) Successful in 22s
CI / backend-lint-and-test (push) Successful in 31s
Build images / build-web (push) Successful in 1m1s
Build images / smoke-web (push) Skipped
Build images / promote (push) Skipped
CI / integration (push) Successful in 2m11s
CI / lint (push) Successful in 4s
CI / extension-version (push) Successful in 3s
Build images / sign-extension (push) Successful in 5s
Build images / build-agent (push) Successful in 8s
Build images / build-ml (push) Successful in 8s
CI / frontend-build (push) Successful in 22s
CI / backend-lint-and-test (push) Successful in 31s
Build images / build-web (push) Successful in 1m1s
Build images / smoke-web (push) Skipped
Build images / promote (push) Skipped
CI / integration (push) Successful in 2m11s
Rule 27 — E5's other half. The matcher can propose; this is where the operator
decides, and where an accepted link actually shows up.
**The review queue** (Settings → Ingestion & filters). Each proposal shows the
per-signal breakdown, not just the total: "why did it suggest this" is the
question the operator actually has, and a lone percentage cannot answer it. So
a row reads "72% · timing 95% · says so 60%", and the copy states outright that
a pair always needs two reasons — which is the property that stops a busy
posting day from producing false pairs.
The empty state says so explicitly. Nothing proposed is the EXPECTED state most
of the time, and an empty queue that looks like a failure invites turning the
threshold down until it produces noise.
**On the card**, both directions, and accepted links only: the teaser gets "The
full set is in Discord", the drop gets "Announced on Patreon". A pending
proposal is a question for the review queue, never a claim to render beside the
artwork — that distinction is the whole confirm-only design, so it is asserted
in the backend (only `linked` rows reach the payload) and again here.
One detail worth the comment it carries: the link's target is `{ query: {
post_id } }` with no name or path. In vue-router that means "the current route
with these query params", so it works identically from Latest and from Browse —
and, more usefully, the card never reaches for `useRoute()`, which it has no
other reason to know about and which is not available when it is mounted in a
test without a router.
Backend CI on 235393c was green: all 13 E5 tests and migration 0094.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LNXXULQDjVZmbuNa2G9mD9
This commit is contained in:
@@ -114,6 +114,40 @@ describe('PostCard', () => {
|
||||
expect(w.text()).not.toContain('updated')
|
||||
})
|
||||
|
||||
it('shows an accepted announcement link from either end', () => {
|
||||
const teaser = mountComponent(PostCard, {
|
||||
props: {
|
||||
post: {
|
||||
...BASE,
|
||||
associations: [{ id: 7, role: 'announces', post_id: 42 }],
|
||||
},
|
||||
},
|
||||
pinia: freshPinia(),
|
||||
})
|
||||
expect(teaser.text()).toContain('The full set is in Discord')
|
||||
|
||||
const drop = mountComponent(PostCard, {
|
||||
props: {
|
||||
post: {
|
||||
...SYNTH,
|
||||
associations: [{ id: 7, role: 'announced_by', post_id: 1 }],
|
||||
},
|
||||
},
|
||||
pinia: freshPinia(),
|
||||
})
|
||||
expect(drop.text()).toContain('Announced on Patreon')
|
||||
})
|
||||
|
||||
it('shows no link when there is no accepted association', () => {
|
||||
// Pending proposals never reach the payload, so an empty list here is
|
||||
// the normal case and must render as silence, not an empty row.
|
||||
const w = mountComponent(PostCard, {
|
||||
props: { post: { ...BASE, associations: [] } },
|
||||
pinia: freshPinia(),
|
||||
})
|
||||
expect(w.find('.fc-post-card__assoc').exists()).toBe(false)
|
||||
})
|
||||
|
||||
it('singularises a one-message drop', () => {
|
||||
const w = mountComponent(PostCard, {
|
||||
props: { post: { ...SYNTH, synthesis: { message_count: 1 } } },
|
||||
|
||||
Reference in New Issue
Block a user