Connor spotted a Missouri redistricting story labelled ohio-state-politics. Measuring showed that was not an isolated slip: 66% of the winners of a place-based block named no place at all. Glastonbury, Anthony Albanese and a Tim Montgomerie story were all scoring as italy-mexico; a singing-apraxia story was ohio-state-politics. Embeddings model meaning well and named entities poorly -- "Italian politics" and "Australian politics" are nearly the same vector. Place is identity, not meaning, so it is matched lexically, which is the same division of labour that makes lexical comparison right for syndication detection and wrong for clustering. Blocks carry `requires_any`; a block cannot win for an item whose text names none of its terms. Word boundaries, not substrings: "rome" is inside "chrome" and "mali" inside "normalise". That is the trap the old blocklist fell into with "nfl" inside "conflict". The first implementation was wrong in a way worth recording, because it looked correct and measured almost unchanged (66% -> 30%). It wrote a sentinel into the RAW score before normalisation -- but when most items are gated, that sentinel becomes the block's own mean, so a gated item z-scored to roughly zero and could still win. Normalisation erased the gate. Applied after normalisation instead: 66% -> 0%, and place-block winners fell from 140 to 10, so 130 items now land in the block they actually belong to.
485 lines
20 KiB
TOML
485 lines
20 KiB
TOML
# Machine-readable form of profile.md. Every `probes` string is embedded into a
|
|
# vector; an item's score for a block is the MAX cosine over that block's probes,
|
|
# never the mean. Probes are written as prose resembling article text, because
|
|
# that is what they are compared against.
|
|
#
|
|
# Blocks are compared by z-score WITHIN block, then multiplied by `weight`.
|
|
# See profile/CALIBRATION.md -- raw cosine is not comparable across blocks.
|
|
|
|
schema_version = 2
|
|
|
|
# =========================================================== interests =======
|
|
|
|
# `group` shares one notification quota across related blocks. Without it the
|
|
# five conflict-* blocks could each claim an alert slot and fill a day with the
|
|
# same subject -- which is what happened: 5 of 5 alerts were Middle East.
|
|
#
|
|
# --- foreign affairs, split from armed conflict ------------------------------
|
|
# Connor: "my actual war interest is low, but unfortunately all wars are
|
|
# important." The click history looked war-heavy only because world-news feeds
|
|
# are war-heavy. Statecraft is the standing interest; combat reporting is
|
|
# routed by importance instead. Keeping them in one block conflated the two.
|
|
|
|
[[interest]]
|
|
id = "diplomacy-foreign-policy"
|
|
weight = 0.9
|
|
probes = [
|
|
"China expands its influence abroad through investment, diplomacy and security agreements.",
|
|
"US foreign policy shifts as the administration reconsiders its posture toward an ally.",
|
|
"The United Nations Security Council debates sanctions and an arms embargo.",
|
|
"Two governments sign a treaty realigning trade and security ties in the region.",
|
|
"A diplomatic crisis erupts as one country expels another's ambassador.",
|
|
]
|
|
|
|
# The A-E ordering Connor gave, encoded as weights. Even the lowest band still
|
|
# reaches him -- but through importance, on major developments only.
|
|
[[interest]]
|
|
id = "conflict-anti-imperial"
|
|
group = "conflict" # (A) top of his ordering
|
|
weight = 0.9
|
|
probes = [
|
|
"An armed liberation movement fights a colonial or occupying power for self-determination.",
|
|
"A socialist or revolutionary force gains ground against a US-backed government.",
|
|
"Anti-imperialist resistance movements coordinate against foreign military presence.",
|
|
]
|
|
|
|
[[interest]]
|
|
id = "conflict-us-involved"
|
|
group = "conflict" # (B)
|
|
weight = 0.85
|
|
probes = [
|
|
"US forces carry out strikes and the administration defends the legal basis for the war.",
|
|
"American troops, weapons or funding are central to an ongoing foreign conflict.",
|
|
]
|
|
|
|
[[interest]]
|
|
id = "conflict-mideast-israel"
|
|
group = "conflict" # (C)
|
|
weight = 0.8
|
|
probes = [
|
|
"Israeli forces strike targets in Gaza, Lebanon or Syria amid continuing escalation.",
|
|
"Ceasefire negotiations falter amid disputes over withdrawal and prisoner exchange.",
|
|
"Palestinians face displacement, demolition and occupation in the West Bank.",
|
|
]
|
|
|
|
[[interest]]
|
|
id = "conflict-undercovered"
|
|
group = "conflict" # (D)
|
|
weight = 0.75
|
|
probes = [
|
|
"Fighting intensifies in Sudan as famine spreads and aid convoys are blocked.",
|
|
"Armed groups clash in the eastern Democratic Republic of Congo, displacing thousands.",
|
|
"Conflict in Myanmar, the Sahel or Yemen continues with little international attention.",
|
|
]
|
|
|
|
[[interest]]
|
|
id = "conflict-general"
|
|
group = "conflict" # (E) -- low interest, still important
|
|
weight = 0.45
|
|
probes = [
|
|
"Front-line fighting continues as both sides exchange drone and artillery strikes.",
|
|
"A long-running interstate war grinds on with incremental territorial changes.",
|
|
]
|
|
|
|
# --- space and aerospace -----------------------------------------------------
|
|
# Connor is an aerospace engineer. He asked for launches/missions/spacecraft,
|
|
# deep technical, and astronomy/planetary science -- deliberately NOT the
|
|
# industry-and-contracts beat, which his policy blocks would catch anyway.
|
|
[[interest]]
|
|
id = "space-aerospace"
|
|
weight = 0.95
|
|
probes = [
|
|
"The rocket lifted off carrying the spacecraft to orbit; the booster landed and the mission reached its next milestone.",
|
|
"Engineers trace a launch failure to a propulsion anomaly and publish the post-mortem.",
|
|
"Propulsion, materials and orbital mechanics choices shape the vehicle's design trade-offs.",
|
|
"A planetary probe returns data from its flyby, reshaping models of the body's formation.",
|
|
"Astronomers report observations of exoplanets, galaxies or a transient event from a space telescope.",
|
|
"A crewed mission's schedule slips as the spacecraft completes qualification testing.",
|
|
]
|
|
|
|
[[interest]]
|
|
id = "science-discovery"
|
|
weight = 0.8
|
|
probes = [
|
|
"Researchers report a finding that overturns the prevailing explanation in the field.",
|
|
"A study in physics, biology or archaeology reveals something previously unknown.",
|
|
"New evidence changes scientists' understanding of a long-standing question.",
|
|
]
|
|
|
|
[[interest]]
|
|
id = "environment-ecology"
|
|
weight = 0.75
|
|
probes = [
|
|
"Protections for an endangered species are rolled back, alarming conservation biologists.",
|
|
"An ecosystem shifts as habitat loss and invasive species reshape which animals survive.",
|
|
"Public land and wildlife management rules are rewritten.",
|
|
]
|
|
|
|
# --- software and systems (push-eligible) ------------------------------------
|
|
[[interest]]
|
|
id = "software-systems"
|
|
weight = 0.9
|
|
push_eligible = true
|
|
probes = [
|
|
"Running large language models locally: quantization, throughput, context length and memory bandwidth on consumer hardware.",
|
|
"A new open-weights model is released with benchmarks and quantized builds available.",
|
|
"A new release of the systems programming language changes the compiler, borrow checker or toolchain.",
|
|
"WebAssembly gains new capabilities for running compiled code in the browser.",
|
|
"Self-hosting a service stack with containers, reverse proxies and automated deployment.",
|
|
"A widely used open source project announces a breaking change, a license change, or a governance dispute.",
|
|
# Connor's words: "Linux news in general. The ricing world/neovim configs/etc"
|
|
"A Linux desktop release brings changes to the compositor, window manager and display stack.",
|
|
"Customizing a desktop setup: window manager configuration, terminal theming, dotfiles and Neovim plugins.",
|
|
]
|
|
|
|
# --- policy and political economy --------------------------------------------
|
|
[[interest]]
|
|
id = "tech-science-policy"
|
|
weight = 0.9
|
|
probes = [
|
|
"Regulators propose new rules governing artificial intelligence development and deployment.",
|
|
"A court ruling reshapes platform liability and online speech regulation.",
|
|
"Government surveillance powers and encryption policy face legal challenge.",
|
|
"Public research funding is cut, reshaping the scientific workforce.",
|
|
"Antitrust enforcement targets dominant technology firms.",
|
|
]
|
|
|
|
[[interest]]
|
|
id = "labor-inequality"
|
|
group = "left-politics"
|
|
weight = 0.85
|
|
probes = [
|
|
"Workers vote to unionize after a long organizing campaign; the employer contests the result.",
|
|
"A strike over wages and staffing shuts down operations across the sector.",
|
|
"New research documents widening wealth inequality and stagnant real wages.",
|
|
"Lawmakers debate expanding public healthcare, childcare and paid leave.",
|
|
"Tenants organize against rising rents as an eviction wave builds.",
|
|
]
|
|
|
|
[[interest]]
|
|
id = "left-movements"
|
|
group = "left-politics"
|
|
weight = 0.85
|
|
probes = [
|
|
"A socialist party wins a decisive election, shifting the governing coalition leftward.",
|
|
"A mass movement mobilizes in the streets demanding redistribution and public ownership.",
|
|
"Cooperatives, mutual aid networks and tenant unions expand their organizing base.",
|
|
]
|
|
|
|
[[interest]]
|
|
id = "anticolonial-sovereignty"
|
|
group = "left-politics"
|
|
weight = 0.8
|
|
probes = [
|
|
"Indigenous communities win recognition of land rights against extractive industry.",
|
|
"A former colony renegotiates resource contracts and asserts control over its minerals.",
|
|
"IMF and World Bank conditionality drives austerity, prompting debt-relief demands.",
|
|
]
|
|
|
|
# Tracked as a threat, not out of sympathy. Connor's AfD and Tate clicks fit here.
|
|
[[interest]]
|
|
id = "far-right-watch"
|
|
weight = 0.75
|
|
probes = [
|
|
"A far-right party surges in a regional election, unsettling the political mainstream.",
|
|
"An authoritarian government consolidates power over courts, press and elections.",
|
|
"Extremist organizing and street violence grow as mainstream parties adopt their rhetoric.",
|
|
]
|
|
|
|
[[interest]]
|
|
id = "political-theory"
|
|
group = "left-politics"
|
|
weight = 0.7
|
|
probes = [
|
|
"An essay argues about socialism, imperialism and political economy, drawing on history rather than reporting a news event.",
|
|
"A critical analysis of capitalism's structure and its alternatives.",
|
|
]
|
|
|
|
[[interest]]
|
|
id = "us-national"
|
|
weight = 0.8
|
|
probes = [
|
|
"Congress advances major legislation after a contested floor fight.",
|
|
"The Supreme Court issues a ruling with sweeping consequences for federal policy.",
|
|
"Federal agencies are restructured by executive order, prompting legal challenges.",
|
|
]
|
|
|
|
# `requires_any` gates a block on a literal, word-boundary mention. Embeddings
|
|
# model meaning well and named entities poorly -- "Italian politics" and
|
|
# "Australian politics" are nearly the same vector -- so 66% of the winners of a
|
|
# place block named no place at all: Glastonbury and Anthony Albanese were
|
|
# scoring as italy-mexico, and a singing-apraxia story as ohio-state-politics.
|
|
# Place is identity, not meaning, so it is matched lexically.
|
|
#
|
|
# --- place -------------------------------------------------------------------
|
|
[[interest]]
|
|
id = "urbanism"
|
|
weight = 0.8
|
|
probes = [
|
|
"The city council votes to reform zoning rules and allow denser housing near transit.",
|
|
"A new bus rapid transit and light rail line reshapes how residents move through the city.",
|
|
"Planners redesign streets to reduce traffic deaths and reclaim space from cars.",
|
|
"A downtown redevelopment project raises questions about displacement and public space.",
|
|
]
|
|
|
|
[[interest]]
|
|
id = "cincinnati"
|
|
requires_any = ["cincinnati", "hamilton county", "northern kentucky", "covington", "newport", "over-the-rhine", "ohio"]
|
|
group = "local"
|
|
weight = 0.9
|
|
local = true
|
|
probes = [
|
|
"Cincinnati city council votes on a budget, a zoning change or a development project downtown.",
|
|
"A regional transit plan or street redesign changes how people move around Cincinnati.",
|
|
"Rent, eviction and homelessness policy in Hamilton County; a local union drive or strike.",
|
|
"Neighborhood institutions, local arts, food and community life in Cincinnati.",
|
|
"Local news from Cincinnati and Hamilton County, Ohio.",
|
|
]
|
|
|
|
[[interest]]
|
|
id = "kentucky-louisville"
|
|
requires_any = ["kentucky", "louisville", "frankfort", "lexington"]
|
|
group = "local"
|
|
weight = 0.6
|
|
local = true
|
|
probes = [
|
|
"Louisville and Kentucky state politics, legislation and local government decisions.",
|
|
]
|
|
|
|
# The level above city hall: Connor asked for Ohio and Kentucky statehouse
|
|
# coverage alongside Cincinnati city government.
|
|
[[interest]]
|
|
id = "ohio-state-politics"
|
|
requires_any = ["ohio", "columbus", "cleveland", "toledo", "dayton", "akron", "statehouse"]
|
|
group = "local"
|
|
weight = 0.75
|
|
local = true
|
|
probes = [
|
|
"The Ohio statehouse passes legislation over the governor's objection.",
|
|
"Redistricting, election law and statewide ballot measures in Ohio.",
|
|
]
|
|
|
|
# Connor follows both for politics, but also because he is learning the
|
|
# languages and expects to travel there -- so culture and popular culture count
|
|
# as signal here, not noise. He said: "pop culture stuff from Mexico/Italy is
|
|
# even ok. Learning the culture helps me learn the language and travel there
|
|
# better." That makes this the one block where lifestyle content is wanted, so
|
|
# the consumer-lifestyle veto must not swallow it.
|
|
[[interest]]
|
|
id = "italy-mexico"
|
|
requires_any = ["italy", "italian", "rome", "milan", "naples", "sicily", "meloni", "mexico", "mexican", "mexico city", "sheinbaum", "guadalajara", "monterrey"]
|
|
weight = 0.75
|
|
probes = [
|
|
"Italian politics, government coalitions and social policy in Italy.",
|
|
"Mexican politics, security policy and the relationship with the United States.",
|
|
"Regional life, cost of living and transport across Italy; what is changing in its cities.",
|
|
"Mexican and Italian music, film, television and food culture; what people are talking about.",
|
|
]
|
|
|
|
# Confirmed by Connor 2026-09-08: wanted, at a level that keeps him up to date
|
|
# rather than saturating the feed.
|
|
[[interest]]
|
|
id = "global-south"
|
|
weight = 0.7
|
|
probes = [
|
|
"An international company withdraws from several African markets amid regulatory pressure.",
|
|
"Elections and political upheaval reshape governments across Latin America.",
|
|
"Infrastructure and economic development across South Asia strains under rapid growth.",
|
|
]
|
|
|
|
[[interest]]
|
|
id = "energy-climate"
|
|
weight = 0.6
|
|
probes = [
|
|
"Grid operators struggle to connect new renewable generation as storage capacity lags demand.",
|
|
"A national climate policy sets emissions targets and restructures energy subsidies.",
|
|
]
|
|
|
|
# =========================================================== vetoes ==========
|
|
# Hard vetoes only for categories that never overlap a real interest. Anything
|
|
# that *might* overlap is a demote instead -- see below. This split exists
|
|
# because a hard veto on a sports-adjacent region killed "Belgian mayor blocks
|
|
# club from hosting Israeli opponent in Europa League", which is Middle East
|
|
# politics. Overlap is the norm, not the exception.
|
|
|
|
[[veto]]
|
|
id = "us-big-three-sports"
|
|
threshold = 0.60
|
|
probes = [
|
|
"The team beat their rivals in a game recap with final scores, statistics and player performances.",
|
|
"A player is traded, drafted or signs a contract; the league fines a franchise over salary cap rules.",
|
|
"Playoff standings, betting lines and a schedule of games on television this week.",
|
|
"Morales homers and drives in four as the Nationals top the Braves 9-5; Snell throws six shutout innings.",
|
|
"Box score summary: hits, runs, errors, pitching line and inning-by-inning scoring.",
|
|
]
|
|
|
|
[[veto]]
|
|
id = "royal-celebrity-gossip"
|
|
threshold = 0.60
|
|
probes = [
|
|
"The royal family attends an event; speculation continues about the couple's status and future.",
|
|
"Celebrity red carpet appearances, box office returns and influencer controversy.",
|
|
]
|
|
|
|
[[veto]]
|
|
id = "consumer-lifestyle"
|
|
threshold = 0.60
|
|
probes = [
|
|
"The best products to buy this week, ranked, with deals and discount codes.",
|
|
"Horoscopes, quizzes, recipes and a travel guide to the perfect weekend away.",
|
|
"Personal finance tips: how to budget, save and pick a credit card.",
|
|
]
|
|
|
|
# =========================================================== demotes =========
|
|
# Penalty applied to the interest score, not a hard exclusion. These categories
|
|
# each sit adjacent to something Connor genuinely wants, so removing them
|
|
# outright would take real stories with them.
|
|
|
|
# Adjacent to: tech-science-policy (AI regulation) and software-systems (local
|
|
# inference). A hard veto here would be actively harmful.
|
|
[[demote]]
|
|
id = "crypto-ai-hype"
|
|
penalty = 1.0
|
|
probes = [
|
|
"The token surged after the exchange listing as investors piled into the crypto rally.",
|
|
"The startup raised a funding round at a multibillion-dollar valuation to build AI agents.",
|
|
"A company announces its new AI-powered product will transform the industry.",
|
|
]
|
|
|
|
# Adjacent to: far-right-watch. "X said Y and Z reacted" is noise; a far-right
|
|
# party winning a state is not.
|
|
[[demote]]
|
|
id = "culture-war-outrage"
|
|
penalty = 1.0
|
|
probes = [
|
|
"A politician's remark sparked backlash online and critics demanded an apology.",
|
|
"A manufactured controversy over a advertisement or a celebrity's comment dominates social media for a day.",
|
|
]
|
|
|
|
# Adjacent to: policing and criminal-justice policy, which Connor does want.
|
|
[[demote]]
|
|
id = "true-crime-blotter"
|
|
penalty = 0.8
|
|
probes = [
|
|
"Police arrested a suspect in the killing; the trial opens with jury selection this week.",
|
|
"A missing person case takes a turn as investigators search a rural property.",
|
|
]
|
|
|
|
# Recurring columns, link round-ups and daily photo features. These are often
|
|
# genuinely on-topic -- Astronomy Picture of the Day matches space-aerospace
|
|
# correctly -- but a feature that publishes on a schedule is not news breaking,
|
|
# and should never be an interruption. Demoted rather than vetoed so they still
|
|
# reach the digest.
|
|
[[demote]]
|
|
id = "recurring-feature"
|
|
penalty = 1.5
|
|
probes = [
|
|
"Catching Our Eye: a round-up of links and short items we noticed this week.",
|
|
"Astronomy Picture of the Day: today's image, with a short explanatory caption.",
|
|
"Your morning briefing: everything you need to know today, in five bullet points.",
|
|
"This week in review: the stories we covered, collected.",
|
|
]
|
|
|
|
# Release feeds publish nightly and prerelease builds continuously. They match
|
|
# software-systems correctly and are worthless as notifications -- the first
|
|
# alert this block ever won was "Nvim development (prerelease) build".
|
|
[[demote]]
|
|
id = "prerelease-build"
|
|
penalty = 1.5
|
|
probes = [
|
|
"Nightly development prerelease build, automatically generated from the main branch.",
|
|
"Release candidate rc1: pre-release for testing, not recommended for production.",
|
|
]
|
|
|
|
# ============================================= the importance lane ===========
|
|
# Independent of interest. Vetoes still apply here -- v0.2's bypass lane ignored
|
|
# relevance entirely (gate.rs:302), which let blocklisted items fire at priority 5.
|
|
|
|
[[importance]]
|
|
id = "war-escalation"
|
|
weight = 1.0
|
|
probes = [
|
|
"One state launches military strikes on another, marking a major escalation of the conflict.",
|
|
"Nuclear facilities are targeted or a state signals willingness to use weapons of mass destruction.",
|
|
"A major new offensive opens a front, or a ceasefire is signed and takes effect.",
|
|
]
|
|
|
|
[[importance]]
|
|
id = "mass-casualty"
|
|
weight = 1.0
|
|
probes = [
|
|
"A powerful earthquake kills hundreds and leaves many missing under collapsed buildings.",
|
|
"A bombing, shooting or industrial disaster causes mass casualties.",
|
|
"A passenger aircraft or train crash kills dozens.",
|
|
]
|
|
|
|
[[importance]]
|
|
id = "us-federal-shock"
|
|
weight = 0.9
|
|
probes = [
|
|
"A constitutional crisis unfolds as the administration defies a court order.",
|
|
"The federal government shuts down after Congress fails to pass funding.",
|
|
"The Supreme Court overturns long-standing precedent.",
|
|
]
|
|
|
|
[[importance]]
|
|
id = "economic-break"
|
|
weight = 0.9
|
|
probes = [
|
|
"Stock markets plunge in the steepest single-day fall in years as a major bank fails.",
|
|
"A currency collapses and the central bank intervenes with an emergency rate decision.",
|
|
]
|
|
|
|
[[importance]]
|
|
id = "us-political-event"
|
|
weight = 0.9
|
|
probes = [
|
|
"A major election is called, delivering a decisive result and a shift in power.",
|
|
"A prominent political figure dies or resigns unexpectedly.",
|
|
]
|
|
|
|
# =========================================================== delivery ========
|
|
|
|
[delivery]
|
|
digest_hour = "08:45"
|
|
quiet_hours = { start = "22:00", end = "07:00" }
|
|
# The importance lane MAY override quiet hours. The interest lane never may.
|
|
importance_may_wake = true
|
|
# No format filter: Connor reads analysis, wire copy, investigations AND opinion,
|
|
# so writing style is deliberately not a scoring axis. This also confirms the old
|
|
# config's notify_opinions = true was intentional.
|
|
format_filter = false
|
|
# Filter-bubble counterweight. The digest always reserves slots for items that
|
|
# scored well on quality and importance but POORLY on the interest profile,
|
|
# labelled "outside your usual". Notifications stay strictly on-profile; this is
|
|
# a reading surface, not an interruption.
|
|
serendipity_slots = 3
|
|
|
|
# The digest is a complete record of the day, including items that already
|
|
# fired a notification -- not just the leftovers.
|
|
digest_includes_notified = true
|
|
# Saturday and Sunday editions run longer and lean toward longform, analysis and
|
|
# the serendipity slots.
|
|
weekend_digest_multiplier = 2.0
|
|
|
|
# Aggregator maturation. An HN post at 3 points is noise; the same post at 300
|
|
# is news. Items below this score are ingested and clustered but never scored
|
|
# for routing, so the system waits for the crowd instead of firing on arrival.
|
|
hn_min_score = 150
|
|
|
|
# Feedback stays binary: interested / not interested. Low friction matters more
|
|
# than richness here -- the model wants many labels, and the old system's
|
|
# failure was collecting 32 of them, not collecting shallow ones.
|
|
feedback_actions = ["interested", "not_interested"]
|
|
|
|
# Embedding is English-only by default (see config.toml [embedding]). Measured
|
|
# 2026-09-08: the same story in Spanish and English scored 0.758 and 0.600
|
|
# cosine against a random-pair p99 of 0.634, so one of two translation pairs
|
|
# was indistinguishable from an unrelated article. Italy and Mexico are
|
|
# therefore covered by English-language sources.
|
|
# Conflict outside categories A-D notifies only on a major development -- a new
|
|
# offensive, a ceasefire, mass casualties, a state entering. Routine front-line
|
|
# reporting goes to the digest.
|
|
conflict_general_requires_importance = true
|
|
|