feat(linkedin-studio): RE-R3d — temporal overlay (first-mover + saturation) [skip-docs]
R3 slice (b): the rest of hull #3. The morning brief now reads the temporal axis the R3b seen-log records but the ranking ignored. Two DERIVED signals, computed at brief time from already-persisted fields (publishedAt/capturedAt -> ageDays, surfacedCount), never stored: - first-mover: recent (ageDays <= --first-mover-days, default 2) AND never surfaced on a prior day -> ranked up, badge "first ute". Future-dated (ageDays<0) excluded. - saturation: surfaced on >= --saturation-at (default 3) prior days -> ranked down, badge "mettet (Nx)". Self-surfacing (our seen-log), not market coverage. - warming (1..at-1) keeps the R3b "sett Nx" badge but only at >=2 (contract intact); neutral carries no badge. SB1 derived (no schema bump: SCHEMA_VERSION 4 / BRIEF_SCHEMA_VERSION 1 untouched). SB2 the R3a relevance composite stays the PRIMARY sort key; the temporal rank is a new cmp key after pillar-overlap, before effectiveDate -> re-orders only WITHIN a (composite, overlap) tier. temporalSignal is pure (saturationAt clamped >=1). Prior-day surfacings exclude today (via lastSurfacedAt), so a same-day re-render is byte-identical (caught by the R3c run-daily SC7 regression; fixes a latent R3b prior-day imprecision too). brief CLI gains --first-mover-days / --saturation-at; schedule untouched (nightly uses defaults). Wiring: trend-spotter.md (prose), trend-scoring-modes.md (one-line consumer note), README (## Temporal overlay), gate Section 16m (+6 unconditional -> ASSERT floor 111->117), TRENDS_TESTS_FLOOR 192->216. Counts 29/19/27 unchanged. Zero new files. Gate: Passed 132 / Failed 0; trends 216/216; hook suite 139/139 untouched. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011vmzxpsFpc8q19LaogAWLD
This commit is contained in:
parent
5aa7187243
commit
2a8459c674
8 changed files with 474 additions and 43 deletions
|
|
@ -152,6 +152,27 @@ new sources. A double-fire on the same day is a safe no-op (RE-R3b per-day idemp
|
|||
before the brief) plugs into the documented seam in `run-daily.sh` as a later slice (e); a
|
||||
brief-history diff is also a later slice.
|
||||
|
||||
## Temporal overlay (RE-R3d)
|
||||
|
||||
The brief applies a **derived temporal overlay** when it ranks — two signals computed at render time
|
||||
from already-persisted fields (`publishedAt`/`capturedAt` → age, `surfacedCount` → self-exposure), so
|
||||
**nothing new is stored** (`SCHEMA_VERSION` stays 4) and the signal can never go stale:
|
||||
|
||||
- **first-mover** — recent (`ageDays ≤ --first-mover-days`, default **2**) AND never surfaced on a
|
||||
prior day. Ranked up; badge `· 🥇 først ute`. A future-dated trend (`ageDays < 0`) is excluded.
|
||||
- **saturation** — surfaced on `≥ --saturation-at` (default **3**) prior distinct days. Ranked down;
|
||||
badge `· 🔁 mettet (Nx)`. This is **self-surfacing** ("you keep seeing this") from OUR seen-log — not
|
||||
market coverage (that needs external polling, a later slice).
|
||||
- **warming** (surfaced 1..at-1) keeps the RE-R3b `· sett Nx` badge, but **only at ≥2** (that badge
|
||||
contract is unchanged); **neutral** (no exposure signal) carries no badge.
|
||||
|
||||
Ranking integration: the relevance composite (RE-R3a) stays the **primary** sort key; the temporal
|
||||
rank (first-mover↑ / saturated↓) is a new key inserted **after** pillar-overlap and **before** the
|
||||
`effectiveDate` recency tiebreaker — so the overlay only re-orders *within* a (composite, overlap)
|
||||
tier, never overriding relevance. Prior-day surfacings exclude today (via `lastSurfacedAt`), so a
|
||||
same-day re-render is byte-identical. Tune per run with `--first-mover-days N` / `--saturation-at N`
|
||||
(the scheduled nightly run uses the defaults).
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue