Mapping community-consensus practice landscape in framework-level Stack Overflow communities via multi-answer structure.
Case study: [reactjs], 2021–2026 (5y window covering React 17 → 19, the function-component / hooks maturation, and the RSC / server-components era).
Stack Overflow 上「一個 question 多個 answer」的結構,本身就是 collective expert opinion 的 implicit aggregator。不同 answer 間的 practice 分布加上作者社群權威,能定量描述某社群對某類技術議題的共識狀態。
2026-05-29 pivot 後(見 docs/adr/0001–0010):對 developer query 採 LLM-canonicalized retrieval + hierarchical map-reduce practice extraction + community-network-derived authority overlay,揭示 React 社群在 implementation choice 場景下的 practice breakdown shape(形狀詞 consensus / polarization / fragmentation —— 描述性、非驗證分類器);票看形狀、authority 當獨立第二軸(見 docs/spec.md §1.2、docs/signal-table-v2.md),shape 從 breakdown 自然 emergent。
呈現方式是一條 query → bake → dashboard 的 live path:使用者丟一段自然語言 query,系統 resolve 出 query-equivalent canonical group,烤出 practice breakdown,前端以 force-field + 敘事呈現(ADR 0009 cold/warm 路徑、ADR 0010 group identity)。Demo query 以 coverage / answer-author diversity 選取(非 topic typology — shape 是 emergent 的,ADR 0001/0006),在資料覆蓋充足的 query 上做 per-query case study。
CONTEXT.md— 領域語言(query / canonical group / practice / breakdown / authority / cold-warm path),grill-with-docs 慣例放 rootdocs/adr/— Binding architectural decisions0001–0010(pivot、clustering、authority、runtime topology、group identity…)docs/spec.md— team-internal implementation reference(流程、演算法、DB schema)— post-pivot 已對齊 ADRHANDOFF.md— 接手指南:要把專案交給別人時,哪些資料產物要另外傳(gitignored 的大檔)、raw vs processed DB、從零重建路徑report/— 報告草稿(main.tex+references.bib)deliverables/proposal.md— 對外 proposal(動機、文獻、RQ)— pre-pivot 版、待整本改寫或併入最終報告docs/reference/se-api-overview.html— StackExchange API 用法 reference
需求:Python ≥ 3.11、uv、Node + pnpm。
# 1. 後端依賴
uv sync
# 2. 前端依賴
cd web && pnpm install && cd ..
# 3. API keys:複製範本後填值(.env 已 gitignored)
cp .env.example .env
# OPENAI_API_KEY — bake 新 query / 重建 canonical index 需要(LLM + embedding)
# SE_API_KEY — 只有「重抓 SO 原始資料」才需要兩個 process;前端固定打 http://localhost:8000,serve 的 CORS 只放行 :5173:
# 後端 serve plane(warm reads + cold-path 入口)
PYTHONPATH=src uv run uvicorn serve.app:app --reload # → http://localhost:8000
# 前端(另開一個終端機)
cd web && pnpm dev # → http://localhost:5173開 http://localhost:5173:landing 列出已知 groups,點進去看 force-field + 敘事;輸入框丟新 query 走 cold-path(resolve → bake → dashboard)。
資料: 站台需要
data/下的 SQLite 整合匯流排與data/canonical_index/(cold-path RAG 用的語料向量)。兩者是 gitignored 的大產物(合計數 GB),不在 git 裡 —— 取得 / 交接(要傳哪幾顆、raw vs processed、路徑覆寫、從零重建)見HANDOFF.md。
Probe 註: 兩個 active probe (
probe/2026-05-13-*/) 的_se_api.py沿用「.se_api_keyfile」的 self-contained 設計(probe convention:不跨 probe 共用 code)。若要重跑,當下臨時echo "$SE_API_KEY" > .se_api_key(跑完可刪;.se_api_key已 gitignored)。
整合階段的 runtime topology 已定(ADR 0009):三個 plane,SQLite 是唯一整合匯流排 —— 沒有任何模組在 request 時呼叫另一模組的程式碼。
- OFFLINE BAKE(Python batch;慢 / 花 LLM $ / deterministic):corpus fetch → authority → canonical group → per-group
extract → relevance → cluster → aggregate(signal-table)→ narrative → materialize,寫進 SQLite。 - SERVE(FastAPI;薄;ms;request 時不碰 LLM):讀表 / cache,回
BreakdownJSON。endpoints:GET /breakdown·GET /answer·POST /queries(cold-path 入口)·GET /usage。 - PRESENT(SvelteKit SPA):渲染
Breakdown—— Editorial·Ink force-field + martini-glass 敘事。
程式碼是 feature-first 分層(folders 是 dependency 規則的投影;6 條規則見 ADR 0009:contract 為 sink、domains 只依 contract、orchestration 經 ports 依 contract+domains、serve 依 orchestration+store+contract、proxy 隔離、domains 不互相 import):
src/contract/ # 型別 + ports(ADR 0008 seam;domains 只依賴它)
src/canonical/ # query → canonical group:embed + RAG + LLM equivalence gate 〔舊 Module C〕
src/breakdown/ # answer-side practice extraction → cluster → fusion / layout 〔舊 Module D〕
src/authority/ # user-network PageRank authority(A→Q graph) 〔舊 Module B〕
src/ingest/ # SE API → SQLite collector 〔舊 Module A〕
src/store/ # SQLite cache + schema(query_viz_cache 等衍生表)
src/orchestration/ # 冪等 bake driver(resolve→extract→cluster→aggregate→narrative→materialize)
src/serve/ # FastAPI serve plane
web/ # SvelteKit SPA(force-field 視覺 + 敘事)
report/ # LaTeX 報告
probe/ # 探索性檢驗(tag-level survey / window-span / canonical-grouping-density)
data/ # SQLite DB + canonical_index(gitignored,見 HANDOFF.md)
舊的
module_a–module_d平行命名已溶解成上面的分層:A →ingest、B →authority、C →canonical、D →breakdown(+serve/web的 dashboard)。contract/orchestration/store是整合階段才長出的 seam 與匯流排層。
Trunk-based development with short-lived feature branches;不強制 PR review。
- 每個任務開自己的 feature branch(命名沿用分層域名,例如
breakdown-extract-prompt/authority-pagerank) - Merge 前先
git fetch && git rebase origin/main(或 merge main into branch)確保無衝突;然後自己 merge 到 main + push - 建議(不強制)發 PR 的情境:跨域 contract 介面改動(
contract/的 ports / types)、Spec / ADR / pivot-level 變更 - 純 doc typo / hotfix 可直接 push 到 main,commit message 註記
(direct)方便日後回查
git checkout main && git pull
git checkout -b breakdown-extract-prompt
# ... 做事、commit ...
git fetch origin && git rebase origin/main # 確保無衝突
git checkout main && git merge --ff-only breakdown-extract-prompt
git push origin main
git branch -d breakdown-extract-prompt
git push origin --delete breakdown-extract-prompt