fix(backfill): hold the index cursor at the first uningested candidate [backfill, docs, tests] - #217
Merged
Conversation
…e [backfill, docs, tests] Bring the #215 watermark invariant to the backfill-issue-index sweep and recalibrate its per-call limits against the 2026-08-03 production measurement. cursor invariant: the cursor is now held one below the first candidate a call failed to ingest, so the next call reopens on that exact number instead of overtaking it. A 404 (absent) is exempt, since nothing will ever ingest those numbers and holding there would stall the sweep permanently. The stall the invariant does introduce is visible in the response (nextCursor equal to the incoming cursor, failed >= 1) and steppable by hand. constants: DEFAULT 25 -> 15 (largest value measured with failed=0), MAX 100 -> 20 (arithmetic only, under the c ~= 40 ceiling of 24). The 100 ceiling was unreachable. Rationale comments now carry the observation boundary and its arithmetic instead of the old ~5 estimate, and record that production re-measurement is no longer available. 予算切れで見送った候補を cursor が追い越していたため、#210 の掃引では limit=25 で一周したあと limit=15 で再掃引する 2 パスが必要だった。cursor を 止めることで、上限値が多少ずれていても取りこぼしがゼロになる — 正しさが定数の 正確さに依存しない形にするのが本体で、定数の実測合わせはその上での器具の精度。 どの binding が見積もりを超えて消費しているかは未特定のまま(断定しない)。 Regression tests: 4 of the 6 new cursor tests fail when the hold is reverted. Closes #216
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
github-rag-mcp | 7b9e119 | Aug 03 2026, 07:15 AM |
liplus-lin-lay
commented
Aug 3, 2026
liplus-lin-lay
left a comment
Member
Author
There was a problem hiding this comment.
AI self-review (auto mode)
受入基準の充足
issue #216 の修正方針 2 点を満たしている。
| 方針 | 結果 |
|---|---|
| 1. 取り込みそこねた最初の候補の手前で cursor を止める(本体) | 充足。retryBoundary ??= number で最初の失敗を捕らえ、nextCursor = retryBoundary - 1。done は scannedTo >= maxNumber 単独ではなく nextCursor === null になった |
| 2. 定数を実測に合わせ、推定値を推定値で置き換えない | 充足。既定 25 → 15(実測 failed=0)、上限 100 → 20。根拠コメントは 48 呼び出しの観測境界と 24c + O <= 1000 < 25c + O の算術を書いており、~5 を別の推定値に差し替えていない |
CI green(test / CI / Workers Builds)。docs は同一 PR 内(installation 両言語 §15 + 0-requirements 両言語 + index.ts の endpoint ヘッダ)。
diff 実読で確認した点
- cursor が後退しない: 候補は
from + 1以上でfromの初期値がmin(cursor, maxNumber)なので、最小の候補はcursor + 1。したがってretryBoundary - 1 >= cursorが常に成立する。等号がそのまま停止シグナルになる形で、追加の応答フィールドを要していない absentを hold から除外:item === nullでcontinueしretryBoundaryを立てない。issue が唯一の設計分岐として挙げた点で、判断は妥当——404 の番号は永久に取り込めないので、そこで止めると retry の境界ではなく恒久停止になる。liplus-language は実際に 22 件の 404 番号を持つので、除外しなければ本番の掃引が確実に詰まっていたresult.embeddedが false = 実際の embed 失敗:force: trueは hash 一致分岐を飛ばすので必ず embed 経路に入り、返り値はembeddingSucceededそのもの。hash skip が失敗として数えられる経路は無い- dry run の挙動が変わっていない:
retryBoundaryは!dryRunブロック内でしか立たないので、dry run のnextCursorは従来と同じ limitの検証が定数を参照している:src/index.ts:542がMAX_INDEX_BACKFILL_LIMITを直に見ているので、上限を 20 に下げたことが 400 応答にそのまま反映される。本 session で私が投げたlimit=25/50は今後 400 で弾かれる。これが本 issue の狙いどおり- cursor 逆行の不在を
cursor > maxNumberの端でも確認:scannedToがmaxNumberに丸められ候補が空になるのでnextCursor = null、done = true
検証の実効性
新規テスト 7 本のうち 6 本が cursor 不変条件、1 本が定数の envelope。担当が cursor hold を巻き戻すと 6 本中 4 本が落ちることを実走で確認済み。テスト名を読み、停止の可視性(makes a stall visible as a cursor that did not move)と手動での踏み越え(steps over a permanently failing number when the caller advances the cursor)の両方が見張られていることを確認した。受容したトレードオフが仕様として固定されている形。
受容したトレードオフ
- 恒久的に失敗する候補があると掃引が止まる。 #215 の watermark と同じ性質だが、こちらは cron ではなく人間 / AI が駆動する endpoint なので、
nextCursorが入力と同値で返ることとして応答に現れる。cursor = nextCursor + 1で踏み越えられることが docs と実行ログ(held before #N)の両方に書かれている - 上限 20 は算術のみで未実測。 実測済みは 15 だけ。この区別がコメント上で明示されている。本番での再測定は不可能(6 repo すべて 100% 到達済みで候補ゼロ、行を消して候補を作るのは論外)で、その事実も根拠コメントに残っている
scope の逸脱
無し。
次のステップ
auto mode のため human gate 無し。self-review pass → merge。deploy 後の運用作業は無い——現在この endpoint を通る候補は存在しない(全 repo 100%)。変更の効果は次に欠落が生じた時に現れる。
liplus-lin-lay
deleted the
216-backfill-issue-index-per-call-limits-exceed-the-subrequest-budget-at-their-documented-values
branch
August 3, 2026 07:18
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
何を直したか
/admin/backfill-issue-indexの 2 点。本体は cursor 側(構造)で、定数の実測合わせはその上の器具の精度。1. 予算切れで見送った候補を cursor が追い越さない
processAndUpsertIssueが embed 失敗を返した候補について、nextCursorをその候補の 1 つ手前で止める(#215 で issue / PR poller の watermark に入れたのと同じ不変条件)。候補は番号昇順に処理するので、最初の 1 件を押さえれば以降も全部覆える。これで
limitが実際の subrequest 予算より大きすぎても、代償は 1 回分の無駄な呼び出しであって取りこぼしではない。正しさが定数の正確さに依存しないのがこの変更の要点。#210 の掃引では実際に limit=25 で一周 → limit=15 で再掃引の 2 パスが必要だった。absent)は cursor を止めない。 GitHub 側に無い番号は誰が何回試しても取り込めないので、そこで止めると retry の境界ではなく永久停止になるdoneは「番号空間の上端に到達」だけでは立たない。未取り込みの候補が残っていればfalsenextCursorが渡したcursorと同じ値で返りfailed >= 1。手動で越える経路はcursor = nextCursor + 1、run log にもheld before #Nとして出る2. 定数を実測に合わせた
DEFAULT_INDEX_BACKFILL_LIMITfailed=0を実測した最大値MAX_INDEX_BACKFILL_LIMIT100 は到達不能な上限だった(
limit=50で呼び出し全体が 500 で失敗)。根拠コメントは「~5」という推定値を別の推定値で置き換えるのではなく、observation boundary(limit=25で 48 呼び出しすべてがindexed=24 failed=1)とそこからの算術をそのまま書いた。論理呼び出し ~6 に対し実測 ~40 という差について、どの binding が消費しているかは未特定のままにしてある(この PR で機構は断定しない)。本番での再測定は不可能という制約もコメントに残した: #210 の掃引で 6 repo すべて索引 100% に到達したため候補が存在しない。行を消して候補を作るのは論外。よって定数の検証は取得済みの観測データ + unit テストに限られる。
テスト
新規 7 本(cursor 不変条件 6 + 定数 envelope 1)。cursor の hold を戻すと 6 本のうち 4 本が落ちることを確認済み:
doneを立てないcursor = nextCursor + 1で詰まった番号を越えられる全体 256 件 green(vitest 198 + workers pool 58)、
tsc --noEmitclean。docs
docs/installation.md/.ja.md§15:limitの範囲・既定値・レスポンス例、実測コスト(1 候補 ≈ 40 subrequest)、cursor hold と手動 step-over 手順、absentが cursor を止めない理由docs/0-requirements.md/.ja.md: 欠落修復の節に cursor 不変条件とそのトレードオフ実機影響
deploy 後の挙動変化は
limitの受理範囲(1..20)と既定値、およびnextCursorの進み方のみ。索引自体は 6 repo すべて 100% に到達済みなので、この endpoint に現に流れる候補は無い。Closes #216
🤖 Generated with Claude Code