You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Finish the semaphore-tag-sync two-tier rollout (#2184): adopt the ~160 existing hand-curated tags and pick up genuinely new tags, without importing all ~21k SES terms.
What's landed (PR: two-tier sync)
Two-tier applier (srv/lib/semaphore-sync/applier.js): Tier 1 adopts/updates existing rows by semaphoreId then by name, backfilling only taxonomy-owned fields (label, name, titlePath, semaphoreId) — never the editorial flags isActualTag/isInterestItem. Tier 2 INSERTs an unmatched term only when its SES class is in semaphore.sync.intakeClasses, and forces new rows inert (both flags false).
Dry-run class histogram in the run summary (classHistogram, a pre-formatted string) so the FILTER / intake classes can be chosen from real data.
Validate with a second dry run: expect updated ≈ 160 (existing adopted), inserted = only genuinely-new allowlisted terms, editorial flags intact on existing rows.
Flip semaphore.sync.dryRun=false in prod DB — only after the dry run above validates.
Rotate the compromised Semaphore API key (a key was pasted into a chat and must be rotated regardless of the sync work).
Guardrails
Feature flag + all tuning are DB config, never env vars.
Do NOT flip dryRun=false until a dry run shows the expected adopt/insert/flag outcome.
Goal
Finish the semaphore-tag-sync two-tier rollout (#2184): adopt the ~160 existing hand-curated tags and pick up genuinely new tags, without importing all ~21k SES terms.
What's landed (PR: two-tier sync)
srv/lib/semaphore-sync/applier.js): Tier 1 adopts/updates existing rows bysemaphoreIdthen byname, backfilling only taxonomy-owned fields (label,name,titlePath,semaphoreId) — never the editorial flagsisActualTag/isInterestItem. Tier 2 INSERTs an unmatched term only when its SES class is insemaphore.sync.intakeClasses, and forces new rows inert (both flags false).classHistogram, a pre-formatted string) so the FILTER / intake classes can be chosen from real data.ok:falsereturns now record FAILED.dryRundefaults true;intakeClassesempty ⇒ adopt-only.Remaining to finish (tomorrow)
classHistogramfrom the SUMMARY.semaphore.sync.filter(recommended — shrinks the 61 MB fetch), vssemaphore.sync.intakeClassesallowlist; and which SES class(es) define a "wanted" new tag.semaphore.sync.*config in the prod DB (per Tom: set directly in DB now; Admin-UI backfill tracked in Admin UI config backfill for semaphore sync #2477).updated ≈ 160(existing adopted),inserted= only genuinely-new allowlisted terms, editorial flags intact on existing rows.semaphore.sync.dryRun=falsein prod DB — only after the dry run above validates.Guardrails
dryRun=falseuntil a dry run shows the expected adopt/insert/flag outcome.cf targetbefore any prod action.Refs: #2184, #2477 (Admin UI), #2478 (mislog).