Ürün
Idea Codex
Dört açık kaynaktan pazar sinyali toplayan, bunları sorgulanabilir tablolara indirgeyen ve her satırı onu üreten çalışmaya bağlı tutan bir hat.
Neyi topluyor, neyi kabul etmiyor
Dört açık kaynak çalışıyor: Reddit, Hacker News, Steam ve Google Trends. Her birinin ortak bir portun arkasında kendi adaptörü var, gelen her yanıt da hiçbir şey onu okumadan önce sürümlenmiş bir zarfla ham havuza iniyor.
Gerisini şekillendiren kural şu: kaynağı olmayan rakam sıfır ediyor.
Saklanmış bir yanıta kadar izlenemeyen iddialar [UNCITED] işaretini alıyor
ve puanlamada hiç ağırlık taşımıyor. Bu bir iç düzen meselesi olarak
durmuyor; üstüne kurulan şey denetlenebilmek zorunda olan bir analist ve
kimsenin geri yürütemediği bir rakam da tam olarak onun önlemek için var
olduğu hata oluyor.
5
Bounded context
Collection, refinement, analysis, candidates, content safety.
152
Test dosyası
221 kaynak dosyaya karşı, katı tipleme altında yazıldı.
9
Import çiti
Linter'ın denetlediği sözleşmeler; katman kayması CI'da düşüyor.
İndirgeme ile analiz ayrı işler
Sınırı çizmek bir karar kaydı gerektirdi. İndirgeme bir şeyin kendi niteliklerini üretiyor: temizleme, isim öbeği çıkarımı, duygu, hız. Analiz ise şeyler arasındaki yapıyı üretiyor: talep grafı, sıralamalar, kümeler.
Duygu analizini analize koymak daha kolay olurdu ve yanlış olurdu. Tek bir satırı tarif ediyor, yani tek kaynağın yeniden kurulması onu yeniden hesaplamak zorunda; dört kaynağa yayılan bir graf ise bunu yapmamalı.
Uzadıkça ucuzlayan örnekleme
Anlık görüntü sıklığını takvim değil puan belirliyor. Hızlı hareket eden şey sık yeniden örnekleniyor, kimsenin okumadığı şey rotasyondan düşüyor. Bir Steam yorumu, üzerinde durduğu oyunun popülerliğine ters orantılı puanlanıyor; böylece bir avuç dev oyun kuyruğu kaplayamıyor.
Ücretli kaynaklar çekim başına harcama defterine işleniyor ve ücretli bir kaynağa ancak ücretsiz olan denendikten sonra uzanılıyor.
Sistem
Toplama
Kaynak toplayıcıları
Python
Neden
Reddit, Hacker News, Steam ve Google Trends. Her birine tek adaptör, hepsi tek portun arkasında duruyor; beşinci kaynak bu yüzden ikinci bir hat değil, bir adaptör oluyor.
Ham havuz
Python
Neden
Her yanıt, hiçbir şey onu okumadan önce, sürümlenmiş bir zarf altında geldiği gibi saklanıyor. İndirgeyiciler yeniden yazılıp bunun üzerinde tekrar çalıştırılabiliyor; bir determinizm testi de yeniden kurulumun aynı yere düştüğünü kanıtlıyor.
Harcama defteri
Python · DuckDB
Neden
Ücretli kaynaklar çekim başına ölçülüyor. Üstündeki kural şu: ücretli bir kaynağa ancak ücretsiz olan denenip neden yetmediği yazıldıktan sonra uzanılıyor.
İndirgeme
Kaynak başına indirgeyici
Python · spaCy
Neden
Kaynak başına bir tane, ortak bir omurga üzerinde. Temizleme, isim öbeği çıkarımı ve duygu analizi burada oluyor; bu katmanda hiçbir şey iki varlık arasında ilişki uydurmuyor.
Yeniden örnekleme kuyruğu
Python · DuckDB
Analiz
Sinyaller ve graf
Python
İçerik güvenliği
Python
Substrat
İşlenmiş depo
DuckDB · Python
Neden
Dar tablolar ve üzerlerinde ince bir sinyal katmanı duruyor. Her satır onu üreten çekim çalışmasını taşıyor, böylece herhangi bir rakam geldiği çekime kadar geri yürütülebiliyor.
Yüzey
Ürün yüzeyi
TypeScript · Next.js · NestJS · PostgreSQL
Neden
Ayrı bir repo; bu sitedeki SaaS altyapısından fork edildi, o yüzden kiracılık, iki katmanlı kimlik, denetim ve veri haklarıyla açılıyor. Üzerine koyduğu şey okuma yüzeyi oluyor: içeri brief giriyor, dışarı kaynaklı cevap çıkıyor.
1"""Migration refinement:0013 — per-pull-run provenance on entity tables (ADR-0029).23Adds write-once `pull_run_id` (the pull run that produced the row, from the raw4doc) + `first_refined_at` (net-new marker; backfilled = refined_at for existing5rows) to the 6 single-PK entity tables. Composite-PK/snapshot/trends tables are6out of scope (Phase 1b-ii). steam_apps already has first_refined_at (m_0010).7"""89from __future__ import annotations1011import duckdb1213ID = "0013_curated_provenance"1415# (table, needs_first_refined_at) — steam_apps already has it (m_0010);16# steam_reviews does NOT have it (confirmed: m_0004_steam has no first_refined_at17# on steam_reviews, and no subsequent migration adds it before m_0013).18_TABLES = [19 ("reddit_submissions", True),20 ("reddit_comments", True),21 ("hn_stories", True),22 ("hn_comments", True),23 ("steam_apps", False),24 ("steam_reviews", True),25]262728def up(con: duckdb.DuckDBPyConnection) -> None:29 # Ordered in three passes within the migration transaction. DuckDB rejects30 # CREATE INDEX while there are outstanding row UPDATEs in the same31 # transaction, so ALL index creation must happen BEFORE the backfill UPDATEs32 # (ADD COLUMN is DDL and does not count as an outstanding update). On a33 # populated DB the naive add->update->index ordering raises34 # "Cannot create index with outstanding updates".35 # Pass 1 — add columns (DDL).36 for table, needs_fra in _TABLES:37 con.execute(f"ALTER TABLE {table} ADD COLUMN pull_run_id VARCHAR")38 if needs_fra:39 con.execute(f"ALTER TABLE {table} ADD COLUMN first_refined_at TIMESTAMPTZ")40 # Pass 2 — create indexes (before any UPDATE; built on the fresh NULL columns).41 for table, _ in _TABLES:42 con.execute(43 f"CREATE INDEX IF NOT EXISTS {table}_first_refined_idx ON {table}(first_refined_at)"44 )45 con.execute(f"CREATE INDEX IF NOT EXISTS {table}_pull_run_idx ON {table}(pull_run_id)")46 # Pass 3 — backfill first_refined_at for existing rows (UPDATEs last).47 for table, needs_fra in _TABLES:48 if needs_fra:49 con.execute(50 f"UPDATE {table} SET first_refined_at = refined_at WHERE first_refined_at IS NULL"51 )idea-codex430b9e9src/market_research/contexts/refinement/adapters/migrations/m_0013_curated_provenance.pySatır 1 – 5151 satır
"""Migration refinement:0013 — per-pull-run provenance on entity tables (ADR-0029).
Adds write-once `pull_run_id` (the pull run that produced the row, from the raw
doc) + `first_refined_at` (net-new marker; backfilled = refined_at for existing
rows) to the 6 single-PK entity tables. Composite-PK/snapshot/trends tables are
out of scope (Phase 1b-ii). steam_apps already has first_refined_at (m_0010).
"""
from __future__ import annotations
import duckdb
ID = "0013_curated_provenance"
# (table, needs_first_refined_at) — steam_apps already has it (m_0010);
# steam_reviews does NOT have it (confirmed: m_0004_steam has no first_refined_at
# on steam_reviews, and no subsequent migration adds it before m_0013).
_TABLES = [
("reddit_submissions", True),
("reddit_comments", True),
("hn_stories", True),
("hn_comments", True),
("steam_apps", False),
("steam_reviews", True),
]
def up(con: duckdb.DuckDBPyConnection) -> None:
# Ordered in three passes within the migration transaction. DuckDB rejects
# CREATE INDEX while there are outstanding row UPDATEs in the same
# transaction, so ALL index creation must happen BEFORE the backfill UPDATEs
# (ADD COLUMN is DDL and does not count as an outstanding update). On a
# populated DB the naive add->update->index ordering raises
# "Cannot create index with outstanding updates".
# Pass 1 — add columns (DDL).
for table, needs_fra in _TABLES:
con.execute(f"ALTER TABLE {table} ADD COLUMN pull_run_id VARCHAR")
if needs_fra:
con.execute(f"ALTER TABLE {table} ADD COLUMN first_refined_at TIMESTAMPTZ")
# Pass 2 — create indexes (before any UPDATE; built on the fresh NULL columns).
for table, _ in _TABLES:
con.execute(
f"CREATE INDEX IF NOT EXISTS {table}_first_refined_idx ON {table}(first_refined_at)"
)
con.execute(f"CREATE INDEX IF NOT EXISTS {table}_pull_run_idx ON {table}(pull_run_id)")
# Pass 3 — backfill first_refined_at for existing rows (UPDATEs last).
for table, needs_fra in _TABLES:
if needs_fra:
con.execute(
f"UPDATE {table} SET first_refined_at = refined_at WHERE first_refined_at IS NULL"
)- Geriye doğru, ve bilerek. Neyin yeniden çekileceğine zaten işlenmiş olana bakarak karar veriliyor; kimsenin okumadığı şey rotasyondan düşüyor, hızlı hareket eden şey daha sık örnekleniyor. Sabit bir takvim ikisine de aynı parayı harcardı.
Ya bulunur, ya hesaplanır
Motorun beslediği ürün, üzerinde bir analistin oturduğu işlenmiş bir veritabanı oluyor. Bir sorunun cevabı substratta zaten varsa iş bir aramaya dönüşüyor; yoksa hat cevabı hesaplıyor ve substrat onu saklıyor. Veritabanını bayatlamaktan alıkoyan şey bu ikinci yol oluyor, toplamanın takvim yerine puanla sürülmesi de buradan geliyor.
Yüzey kendi reposunda duruyor; SaaS altyapısından fork edildiği için kiracılık, iki katmanlı kimlik, denetim ve veri haklarıyla açılıyor, üzerine de bu ürüne özgü olanı koyuyor: içeri brief giriyor, dışarı kaynaklı cevap çıkıyor. İki taraf birbirinin içine değil yazılı bir sözleşmeye bakıyor; motorun altta biçim değiştirmeye devam edebilmesini de bu sağlıyor.
Katkı
- Yazılan commit
- 420
- Kaydedilen karar
- 38
6 haftanın 4 tanesi aktif · 4 May 2026 – 14 Haz 2026
En uzun seri · 2 hafta · May – May
Yalnızca motor. Yüzey reposu geçmişini altyapıyla paylaşıyor, o iş de orada sayılıyor.
Ölçüm 2026-09-09