Skip to content

Index covers only about 45 percent of issue and PR history #210

Description

@liplus-lin-lay

目的

索引が repo の issue / PR 履歴を網羅していない状態を埋める。設計意図は「過去履歴も含めすべて入れる」だが、実測では半分に届いていない。あわせて、欠落が積み上がる経路を閉じる。

確認済みの事実(2026-08-03 実測)

Liplus-Project/liplus-language:

種別 実物 索引済み(distinct number) 被覆率
issue 919(open 33 / closed 886) 419 46%
pull_request 698(すべて closed) 313 45%

番号帯別の分布(200 刻み、issue / PR):

   0-199 :  15 / 13
 200-399 :   7 /  3
 400-599 :  26 / 17
 600-799 :  24 / 10
 800-999 :  22 / 19
1000-1199:  78 / 61
1200-1399: 111 / 89
1400-1599: 107 / 90
1600-    :  29 / 11

古い番号帯ほど薄い。ただし連続した範囲が丸ごと欠けているのではなく散発で、#600#630 を実物と全件突き合わせた結果は 31 番中 23 件が索引済み、欠落は #600 #601 #602 #603 #605 #606 #608 #626 の 8 件だった。

索引対象 repo 全件の被覆率(2026-08-03 実測。実数 = GitHub の全 state 件数、索引 = search_docs の distinct number):

repo issue 実 / 索引 PR 実 / 索引 欠落計
Liplus-Project/liplus-language 919 / 419 (46%) 698 / 313 (45%) 885
Liplus-Project/github-webhook-mcp 135 / 58 (43%) 113 / 47 (42%) 143
Liplus-Project/github-rag-mcp 105 / 56 (53%) 106 / 40 (38%) 115
Liplus-Project/liplus-desktop 41 / 9 (22%) 48 / 9 (19%) 71
Liplus-Project/dipper_ai 34 / 25 (74%) 29 / 13 (45%) 25
Liplus-Project/neuron-graph-rag 13 / 13 (100%) 12 / 12 (100%) 0
1239

neuron-graph-rag だけが 100%。 件数が 1 run の embedding 上限に収まる規模で、上限に一度も当たっていない repo が唯一取りこぼしゼロという分布は、下記の原因と一致する。

原因(2026-08-03 実装から確定)

embedding budget を使い切った残りが、二度と取りに行かれない。

src/poller.ts processIssues は 1 run あたり MAX_EMBEDDINGS_PER_RUN = 50 件しか embed しない。上限に達した以降の item は bodyHash: "" の record を IssueStore へ書くだけで、search_docs への行は書かれない(FTS mirror は embedding 成功後の経路にしか無い)。設計意図は「空 hash を retry の印にして次 run で拾う」。

ところが pollRepo は watermark を無条件に前進させる:

  • capped = false → watermark = pollStartTime
  • capped = true → watermark = 最後に fetch した issue の updated_at

fetch は sort=updated&direction=asc なので、embed されずに残るのは常に「その batch の中で updated_at が最も新しい側」。どちらの分岐でも watermark はその残りの手前ではなく先に進むため、次 run の since 条件から漏れる。retry の印は付くが、印の付いた item が二度と fetch されない。 embed 自体が失敗した item(failed)も同じ経路で落ちる。

規模も噛み合う: MAX_PAGES_PER_RUN = 2 × PER_PAGE = 100 で 1 run 最大 200 件 fetch に対し embed は 50 件。初回同期時は 1 run ごとに 150 件が落ちる勘定になる。番号順ではなく updated_at 順に落ちるため、欠落は番号帯で見ると散発に見える(実測の分布と一致)。

同型の欠陥が既に別 surface で修正されている。 #179「hold diff watermarks at the first uningested commit」(a7e7d54)が commit-diff 側で同じ構造を潰しており、DIFF_RETRY_BOUNDARY_BACKOFF_MS を含む pin の型が repo 内に既に在る。issue / PR surface へは適用されていなかった。

doc surface は break して blobSha 比較で拾い直すため同じ穴は無い(watermark 依存でないため)。release surface には別種の小さな穴があり、そちらは #211 に分離した。

修正方針

  1. 恒久: embedding budget 到達 / embed 失敗で見送った最初の item を「未取り込み境界」として持ち、watermark をその手前で止める。fix(poller): hold diff watermarks at the first uningested commit [poller, admin, docs, tests] #179 の pin と同型に揃える(since の inclusive 境界に対する backoff margin も同様に必要)。これにより次 run が同じ範囲を取り直し、欠落は積み上がらなくなる。
  2. backfill(既存の欠落分): 再 index は embedding 呼び出しを伴う。上表のとおり全 repo で 1239 件。2026-08-03 に Master の go-sign を取得済み。 恒久修正だけを先に入れても既存の欠落は埋まらない(該当 item の updated_at が動かない限り fetch 対象に入らないため)。
    • backfill は admin endpoint とし、repo 指定・cursor・件数上限を取る形にする。1 run で 1239 件を流すのは Worker の subrequest 予算と Workers AI の rate limit に対して無理があるため、batch を跨げる形が要件。
    • 実行順序は恒久修正 → deploy → backfill。逆順にすると backfill 後に入る新規 item が同じ経路で再び落ちる。

制約

  • 恒久修正と backfill は同一 PR に入れる(issue 1 本 = PR 1 本)。backfill の実行は merge + deploy 後に parent が行う。
  • Rows indexed while open keep a stale open state after the item is closed #209(索引済み行の state 取り残し)とは独立した欠陥。#600#630 の実測では索引済み行の state は全て正しく、欠落と state ずれは別経路であることが確認済み。

対象ファイル

  • src/poller.tsprocessIssues の未取り込み境界の返却、pollRepo の watermark 決定)
  • src/index.ts(backfill admin endpoint。go-sign 後)
  • docs/0-requirements.md / docs/0-requirements.ja.md
  • 回帰テスト

背景

#209 の実測中に副次的に判明した。検索が沈黙したとき、それが「該当が無い」なのか「索引に届いていない」なのか区別できない状態であり、memory/promotion_tally.mdinstrument-unvalidated-zero-read-as-fact(0 件を事実として読む失敗)が構造的に起きうる面になっている。

Metadata

Metadata

Assignees

No one assigned

    Labels

    bug動いていない、壊れているdone役目完了、orchestration (review / merge / close) フェーズ待ちready本文が実装開始できる形まで収束している状態。ただし更新は継続可能

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions