Skip to content

enhancement(search): abstain when top results fall below a confidence threshold #275

Open

Description

@liplus-lin-lay

Codex Luna

目的

検索で見つかった近い別件を、答えの根拠として使ってしまう失敗を減らす。検索結果の拒否・関連度の信号付与を比較調査する。保存済み記憶は削除しない。既定検索はまだ変更しない。

確認した前提(2026-10-12)

  • MemX v1 §3.6/5.7 のA条件は、キーワード検索が空 AND 最大ベクトル類似度 < τ。0.50は同論文の実験値であり、本サービスの採用値ではない。
  • main ca34e9f のfts.ts は strict AND + relaxed OR。キーワード候補ありを強い一致と同一視できない。fix(fts): AND-joined MATCH drops sparse retrieval to zero on natural-length queries #186 の長文取り逃し対策は維持する。
  • mcp.ts の FTS例外は空候補へ縮退し不完全取得状態を立てる。正常な0件・障害・未実行を区別する。post-filter前の候補数と最終対象母集団も区別する。
  • rerank.ts は有効本文1候補で点数1を合成する。callerはfiltered候補1件でrerankを飛ばす。未測定・一部欠落・合成1を実モデルの高/低関連度として扱わない。query200文字/pair1700文字の切り詰めも評価条件。
  • graph_resultsは独立軸(spec(search): return graph-derived results as a separate axis instead of score-0 rows in results #234)。keyword点数でgraph候補を落とさない。scan/fetchは今回の意味検索拒否の対象外。
  • main SHAはGitHubとfetchで確認。本番稼働コードのSHAは未確認で、ライブ応答とソース確認を区別する。

ライブ予備調査(6検索、性能評価ではない)

全件 repo=Liplus-Project/github-rag-mcp、type=issue、top_k=3、既定rrf/rerank。2026-10-12 22:06 JST。

query 第一資料 rerank_score sparse_candidates
low confidence rejection #275 0.159117 4
検索結果の確信が低いときに返さない方式の候補と測定方法 #275 0.995069 15
abstain when top results fall below a confidence threshold #275 0.999856 15
#275で本番採用済みの拒否閾値と精度の実測値は何ですか #275 0.007246 15
What production threshold and measured precision were adopted in issue 275? #275 0.001410 15
月面温室で栽培した紫色トマトの糖度の実測値 #244 0.000054 15

6件全てでsparse候補あり。応答の候補数を使う素朴なAは発火0回。この6件以外で発火しないとは断定しない。#275は低点でも「検討段階」と前提を訂正する資料として有用。同じ本文が数値回答を含まないことと、判断材料として無関係なことは別。

先の0.92/0.22の観測は検索文・候補集合・時点が揃っていない。本文も編集されており、差を言い換えだけに因果帰属しない。月面トマトは負例候補であり、全索引の不存在証明ではない。

生応答と詳細試験案は調査担当workspaceの .artifacts/rag-abstention-275/pilot-2026-10-12.json / investigation.md に保存。上表と採用判断に必要な内容は本issueへ記録し、localファイルだけを引継ぎ根拠にしない。

比較する案(未採用)

  • Baseline: 現行検索を保持。
  • A: MemX二条件。フィルタ済み候補プールの最大dense値と正常取得を計測して判定。τは調整用資料で振る。現行top-k応答だけでは候補全体の最大dense値を常に復元できない。
  • B: 実モデルで測れた検索内最大rerank点数が低い場合に検索全体を空にする。各資料を個別削除する案とは別。未測定/不完全は保持して判定不能を報告。
  • C: Bと同じ信号でも資料は保持し、低い関連度を示す。正しさの確率とは呼ばない。
  • A'(後続候補): キーワードの一致の強さを使う修正版。Aと混ぜず、既存のAND/OR順位を壊さない。

試験案

固定小コーパスと事前ラベルを本番とは別の試験環境へ置く。code SHA、資料hash、索引、モデル、候補数を固定。同じ候補取得結果へ各案を適用する。支持/反証/部分的根拠/無関係を資料ごとの引用箇所で定義し、期待回答(回答/前提訂正/根拠不足)も固定する。

最低出発点は36意図(裏付け9、明示根拠による前提訂正9、誤った前提だが訂正根拠なし9、その他無関係9)×等価な日英/短い探索語3表現=108問い。十分な検出力の保証ではない。前提訂正の正解には状態を明示する引用を要求し、記載の欠如だけで未採用と推測しない。無関係の正解は固定コーパスの監査によって付ける。

意図と資料系列(同じissue/コメント/派生文書・同じ判断のコピー)を連結したグループごとに調整/未使用評価へ分ける。同一資料系列とその言い換えは跨がせない。分割後の各カテゴリ件数・repo数・系列重複0を報告する。#275以外の複数repo・題材を含め、混在資料・旧情報/新情報・本文後半の根拠も入れる。グループで分離できなければ資料を追加し、漏洩したまま評価しない。

一次評価: 無関係資料の返却率、支持/反証/部分的根拠の保持率、誤拒否率、発火率、判定不能率。カテゴリ/言語別の分母・件数を報告する。

二次評価: 同じ資料パケットを読む側へ渡すBaseline/B/C比較。条件名を伏せ、同じモデル/予算/指示で採点する。害(無関係資料からの断定、根拠なしの前提否定)と損失(訂正根拠があるのに根拠不足で停止、支持根拠の取り逃し)は別々の件数として報告し、一つの正誤へ潰さない。根拠不足の適切な明示も数える。Cでは「低点の資料を使わない」を正解にしない。反証資料を適切に使えるかまで測る。

採用条件: 未使用意図で無根拠断定の減少が再現し、支持/反証の損失と追加再検索コストを説明できること。許容損失値は未決定。優位がなければ既定維持。最初の実装を行う場合も診断/shadow評価から始める。

比較演算自体は追加モデル不要。Bは既存rerank実測経路が前提。Cの読取試験と再検索は別途時間/トークンを要する。108検索と読取評価は未実施で、今回実施したのは6検索とソース/論文/issue確認のみ。

Memory Mosaics からの参考点(追加調査、未採用)

原論文 §3/4 は文脈からキー、続く情報から値を作る学習済みの連想記憶で、Gaussian kernelの正規化重みで値を予測する。v2 §3 は記憶数に応じた学習済みbandwidthと短期/長期の別パラメータを持つ。公開コードの確認点 は旧版ContextMem/PersistentMemのsoftmax/attention。旧版コードをv2実装と同一視しない。

RAGへの設計仮説: 話題の近さに加えて「どの条件で、その資料がどの判断を支えるか」を照合する。問いの対象/時点/求める判断を保持した検索キー、資料の主張/成立条件/検証結果/出典を別に扱い、支持と反証を拾えるか評価する。これは論文のニューラル学習機構の直接移植ではない。通常の検索と文脈付き検索の比較を先に行い、条件抽出ミス・索引容量・追加検索/推論コストを測る。事実資料を重み付き平均で融合しない。

D/Eは追加推論を使わない候補分布の診断仮説としてのみ記録する。Dは独立entity間の上位差/集中度。Eは固定embedding/距離/bandwidth/候補数/重複処理のもとでのkernel総量(単なるrerank点数の合計ではない)。小さい差は複数の正しい資料でも生じ、大きい差は無関係な一件だけでも生じうる。正規化した重みは、全候補が遠くても合計1。重複・候補数・尺度の変更でEも変わる。論文の式はD/Eを正答確率や拒否基準として検証していない。D/Eを#275の採用済み制御とせず、まず既存固定候補ログで診断力を見て、有望なものだけ読取比較へ進める。

初回実験結果(2026-10-12、追加モデル/本番変更なし)

既存6応答の後処理では、top点数または独立entityのtop1-top2絶対差にτ=0.01を使うと、探索資料3/3を残しつつ、前提訂正に有用な#275を2/2失った。τ=0.001ならこの小標本は全部残せるが、この表で選んだ閾値の採用や一般性能は主張しない。

別途3題材 × 短文/文脈付き × global/repo指定の12検索(type=doc、top_k=3)を実施。指定した正本の到達を測り、他資料の全般的有用性は未採点。

条件 正本hit@1 正本hit@3 別repoがtop1
短文global 1/3 1/3 1/3
文脈global 0/3 2/3 2/3
短文repo指定 1/3 1/3 0/3
文脈repo指定 1/3 2/3 0/3

題材: github-rag mention関係、NGR未知relation type、webhookprocessed保持。supersedes relation graphのglobal検索では別repoのNGR資料が0.916375で1位。対象を明示しrepo指定した問いでgithub-rag正本が1位になったが0.058730。点数の高さでは対象一致を保証できない。repo指定は別対象の資料を防ぐが、正本の取り逃し自体は解消しなかった。横断調査で常に単一repoを強制しない。

正本を固定main sourceから直接読むと3題材の明示根拠を人手で特定できた。該当箇所180/257/944文字に対し全文20712/51400/24984文字。ただし自動selector、token費用、回答品質の性能評価ではない。NGRの根拠item92は全文offset17563で、索引/本文切り詰めが影響しうるが索引row未確認につきmiss原因は未確定。APIのdirectory-only path_prefixへファイルを渡した3回は拒否され、成功検索に算入しない。補助scan4回のうち古いNGR窓は50件でtruncated、索引不存在を証明していない。

raw/詳細: 調査workspace .artifacts/rag-abstention-275/context-pilot-2026-10-12.json / navigation-pilot-2026-10-12.json / experiment-round-1.md。source main SHAはRAG ca34e9f、NGR e516272、webhook347d860。稼働index/code SHA未固定、初回探索結果のみ。

人間の論点訂正: RAGに入る情報の役割を扱い、Li+ルール変更には寄せない。作業情報/経験情報/基盤知識は役割仮説であり、sourceのdoc/issue/open/closedとは別軸。#275の同じmemo/open本文にも、機構の説明・実測経験・未実施計画が共存するため、type/stateだけでは一意分類できない。名称とschemaは未採用。

既存の印は確認先を絞る手掛かり。recency=supersededは候補内の同一entityに新しいdoc/diffがあるという意味で、判断撤回の証明ではない。現行graphはmention。source-use履歴は判断主張ごとの依存関係とは別で、既存APIだけでTMSが完成するとは主張しない。

最小の有望策: 既知の対象を既存repo filterへ渡す+基盤知識の問いは正本の入口から本文を確認する。自動の役割分類/正本選択は未実装。次の固定試験ではroot不明/複数/誤りを含め、正解rootを評価側に漏らさない。既定結果の拒否はまだ採用しない。

今回の実装段階: 固定captureのoffline replay(人間の並行実験go-sign、2026-10-12)

目的: 同じ入力・ラベル・閾値でbaseline/A/B/Dを再計算し、支持・反証を失う量と判定不能を再現可能にする。既定検索へ拒否やrole分類を追加しない。

必要な成果物: dependency不要のNode CLI、score/ラベルの入力契約、既存6captureからprivate trace/activation/feedback用IDを除いた探索用fixture、意味のある契約テスト、実行方法と解釈上限の文書。既存fixtureは既に観測したdevelopment資料であり、新しいholdoutや一般性能と呼ばない。

判定: 全検索のtop実測rerank点(B)、独立entity top1-top2絶対差(D)、MemXの二条件(A)。missing/nonfinite/合成/部分取得/候補pool不明を0扱いしない。sparseが正常に存在するAは拒否しない。sparse空時に全poolの最大denseを確認できない場合は判定不能として保持する。B/Dも未測定/候補欠落は判定不能。Cは資料を保持するpacketを用意できても、読む側の効果をこのCLIで断定しない。Eは指標未定義なので代用品を作らない。

支持/明示反証/部分的根拠/無関係/未判定を区別する。goldの有用性はcitationと適用条件を含む別annotationとして管理する。全コーパス不存在未確認のmoon質問を確定unanswerableとして採点しない。candidate-level損失とquery全体の無根拠断定を混ぜず、後者は未測定と表示する。whole-query拒否とper-item削除を混ぜない。

schema/protocol/fixture/annotationのhashを結果へ保存し、元captureを書き換えずに再実行できること。固定gridは0,0.001,0.005,0.01,0.05,0.1,0.2,0.5,0.9。thresholdの最適化は行わない。追加の小さな合成controlでscore欠損、同一entity重複、同点、反証資料の低点保持、部分取得、tau境界を検証する。合成controlの成功を検索品質と呼ばない。

想定変更箇所: experiments/abstention-replay/、scripts/のCLI/契約テスト、docs/の実験文書。runtime/認証/DB/公開API/既存検索default/既存凍結artifactは対象外。入力fixtureへcredential、principal、private trace、feedback receiptを入れない。

この実装は次の読取比較の道具。108問いの固定source比較とblind reader評価は別段階であり、完了したと書かない。PR mergeだけで終わらない条件: 読取比較を行い、改善または不採用の理由をissueへ記録するまで本issueを開いた状態に保つ。

— Luna

Activity

  1. added
    enhancement新機能・改善要望
    memoメモとして開始した状態。見出しは必要なものだけでよい
    on Oct 12, 2026
  2. added
    ready本文が実装開始できる形まで収束している状態。ただし更新は継続可能
    and removed
    memoメモとして開始した状態。見出しは必要なものだけでよい
    on Oct 12, 2026
  3. self-assigned this
    on Oct 12, 2026
  4. added
    waiting外部依存待ち(CI / dependent issue / 環境)。pause 状態
    and removed
    in-progress着手中、実装または検証が進行中
    on Oct 12, 2026
  5. lipluscodex commented on Oct 12, 2026

    @lipluscodex
    Member

    Codex Luna

    PR #276 のhead 5a0400bd5ead00bc04e1ddcd3b9fa599bc89656f に対するCI(test/Workers Builds)を待機中。ローカル契約テスト7件とCLI実行は成功。CI完了後に親agentへ報告する。reader比較は別段階として残る。

    — Luna

  6. added
    review-pending実装フェーズ完了。orchestration (brake eval / review / merge / close) 待ち
    and removed
    waiting外部依存待ち(CI / dependent issue / 環境)。pause 状態
    on Oct 12, 2026
  7. added
    in-progress着手中、実装または検証が進行中
    and removed
    review-pending実装フェーズ完了。orchestration (brake eval / review / merge / close) 待ち
    on Oct 12, 2026
  8. lipluscodex commented on Oct 12, 2026

    @lipluscodex
    Member

    Codex Luna

    読取比較の開発試験(2026-10-13)

    既定検索は維持する。自動拒否/低点の注意表示を本番採用する根拠は今回得られなかった。これは一般的な不採用証明ではなく、追加機能をまだ入れない判断。PR #276 は merge commit 139aa6cce8b5ba018923cb5fe0393464f0471245 で実験基盤のみマージ済み。CI全3checkとCLI契約7test成功。runtime/API/DB変更なし。#275 は評価未完了のため再オープンした。

    初回3問(各arm1回、開発用)

    同じ #275 の検証済み本文prefixを3問へ渡したcurated packetであり、検索の全候補packetではない。通常返却・最大返却点数<0.01で全拒否・同条件で注意表示して保持を比較。

    問い 通常 全拒否 注意表示
    方式の候補と測り方 回答 回答 回答
    本番採用済み閾値と精度 未採用と前提訂正 根拠不足(訂正資料を損失) 前提訂正
    月面トマト糖度 根拠不足 根拠不足 根拠不足

    全条件で無根拠断定0/3。負例が遠い・1資料が自己参照的なので追加の近い別件を調べた。無根拠断定が出ない結果は読取promptが対象/時点/条件の確認を明示した条件下のもの。

    追加3問(各arm1回、索引本文を固定)

    問いの型 最大点数 通常 0.20全拒否 同条件注意表示
    T31 同repo: embeddingの60000上限をrerankerに転用 0.299718 対象違いを訂正、数値上限は根拠不足 同じ(不発) 同じ(不発)
    T84 同repo:古い合計budgetが十分か 0.115675 後続本文から前提訂正、現在配備は未確認 根拠不足(訂正資料を損失) 通常と同じ
    T62 複数repo:意味グラフの設計を検索実装と同一視 0.104457 根拠不足、対象とtruncationを区別 根拠不足 通常と同じ

    0.20は事前gridの感度診断で、観測後に選んだ開発条件。採用閾値でも独立holdoutでもない。0.01なら追加3問では拒否/注意表示とも発火0回。全rerank母集団が見えていないため、全pool B/Dの性能とは扱わない。

    追加試験も全条件で無根拠断定0/3、全拒否のみ明示的訂正資料の損失1/3。全quoteが返却excerpt内にあることを機械照合済み。候補数/新旧印/本文の条件は保持arm間で固定。今回の行にrecency印は返っておらず、新旧印の有無比較はしていない。T84の訂正は時刻・本文の明示的退役宣言によるものであり、#267の効果ではない。本文を短縮したarmも無く、全文取得や要約の因果効果も測っていない。

    判断と残る評価

    • 単一の点数閾値で最上位候補を望む順に選べない例がある。ただしT31全packetにはreranker資料 #91もあり、第一候補が対象違い=packet全体が無関係ではない。
    • 注意表示の上積みはこの6問で観測しなかった。統計的優位/同等性/一般的無効は主張しない。
    • 対象repoが既知なら既存repo絞り込みを使う。跨る問いでは強制しない。根拠の対象・条件を本文で確認できる経路を優先する。APIの既定変更なし。
    • 固定108問い、資料系列/意図ごとの未使用評価、読取反復、許容損失・成本の確定は未実施。現時点で精度値や本番閾値は決めない。本文の完全性/要約の比較をNGRへ移す場合は、対象資料をNGRの判断記録で作り直す必要がある(NGR #298/#299)。

    再現用の追加3問packet・protocol・読取JSONは別コメントに保存する。private trace/feedback識別子は掲載しない。

    — Luna

  9. lipluscodex commented on Oct 12, 2026

    @lipluscodex
    Member

    Codex Luna

    近い別件の開発試験:固定パケットと読取結果

    公開資料の索引本文を再現用に保存する。private識別子は含めない。r8のpacketからprotocolの規則でv3/m6を生成する。各armは独立context・同一読取prompt・medium effort・各問1回。提供資料だけで答え、対象・時点・条件・切り詰めを区別し、前提訂正・根拠不足を許すprompt。

    protocol・固定パケット・出力・検証結果
    {
      "protocol": {
        "protocol": "near-reader-development/v1",
        "created_before_reader_outputs": true,
        "selection": "development controls deliberately chosen after earlier pilot; not holdout",
        "arms": {
          "r8": "baseline",
          "v3": "returned-packet maximum <0.20: empty packet",
          "m6": "same rule: low relevance note, retain all"
        },
        "threshold": "0.20 is grid sensitivity diagnostic, not production choice; full rerank pool unknown",
        "invariants": "original repo/state/version/recency fields and excerpt bytes same across retained arms; no recency field returned for these captures; no extra recency ablation or manual newer stamp",
        "reader": "independent fresh context, inherited model, medium effort, each case once; common prompt explicitly requests subject/time/truncation caution; cannot estimate unassisted deployment behavior",
        "cases": [
          {
            "case_id": "T31",
            "kind": "same_repo_wrong_component",
            "gold": "Do not transfer embedding batch 60000/count*max to reranker. #246 is embedding; #91 says verify input cap and does not supply it. Cannot establish current numeric reranker limit. Accept correction with explicit numeric insufficiency.",
            "max": 0.29971787333488464
          },
          {
            "case_id": "T84",
            "kind": "same_repo_historical_budget_change",
            "gold": "#246 explicitly challenges sum-based budget used in #244 and proposes count*max. Historical proposal not proof current deployed configuration nor official provider billing. Accept premise correction for historical proposed algorithm plus deployment caveat.",
            "max": 0.11567467451095581
          },
          {
            "case_id": "T62",
            "kind": "cross_repo_design_vs_implementation_truncated",
            "gold": "Decision-Structure docs describe semantic judgment relation vocabulary but do not establish github-rag parser behavior. github-rag requirement excerpt is first8000 chars with relevant graph specification missing. Should not claim semantic supersedes implementation from other repo; current actual graph behavior insufficient in provided packet.",
            "max": 0.10445662587881088
          }
        ],
        "metrics": [
          "unsupported claim from wrong subject",
          "loss of explicit corrective evidence",
          "current deployment inference from historical design",
          "truncation acknowledged"
        ],
        "limitations": [
          "3developmentcases",
          "1readerperarm",
          "scorefullpoolunknown",
          "indexed historical versions, not live current GitHub bodies",
          "prior snapshot three #275 arms same one source curated not full candidate packet"
        ]
      },
      "baseline_packet": {
        "protocol": "near-reader-development/v1",
        "packets": [
          {
            "case_id": "T31",
            "question": "github-rag-mcp の bge-reranker-base は batch 件数 × 最長入力で 60000 トークンまで使えますか",
            "retrieval_note": null,
            "sources": [
              {
                "source_id": "T31S1",
                "repo": "Liplus-Project/github-rag-mcp",
                "title": "fix(pipeline): bound embed batches by count times longest input, not by total",
                "url": "https://github.com/Liplus-Project/github-rag-mcp/issues/246",
                "source_updated_at": "2026-08-15T01:22:01Z",
                "rerank_score": 0.29971787333488464,
                "state": "closed",
                "content_truncated": false,
                "excerpt": "fix(pipeline): bound embed batches by count times longest input, not by total\n\n## purpose\n\nWorkers AI の batch embed が拒否する量は、入力の**合計**ではなく **`batch 件数 × batch 内の最長入力`** である可能性が高い。#236 / #241 / #244 は 3 回とも合計を縛っており、縛る対象そのものが違っていた。境界の形を変える。\n\n## observation\n\n`0411f101`(#244 の UTF-8 バイト版)が 8 時間前から 100% traffic で稼働中。それでも 2026-08-15 09:30 JST の cron で同じ失敗が出る。\n\n```\nFailed to batch-embed diffs for Liplus-Project/neuron-graph-rag@1fb0f6b397c1ff333d698fe58a862b9583b463fe\n  chunk offset 0: 3030: Max context reached 60678 tokens but model supports only 60000\n```\n\n18 file が `chunk offset 0` の 1 batch。そして **60,678 という報告値が #242 の前から一度も変わっていない**。推定トークン軸・文字数軸・バイト数軸の 3 つを通しても同一である以上、batch の組み方が変わっていないことになる。\n\n### 報告値を件数で割ると全て整数になる\n\n| commit | batch 件数 | 報告値 | 商 |\n|---|---|---|---|\n| `1fb0f6b397c1ff333d698fe58a862b9583b463fe` | 18 | 60,678 | **3,371** |\n| `bdf8b62bfc8cc88944d342ab0cefc1f544edfa5c` | 17 | 64,413 | **3,789** |\n| `92eb94dcb88c5e7494bc3b69377249e08601d99f` | 20 | 85,920 | **4,296** |\n| `92eb94dcb88c5e7494bc3b69377249e08601d99f` | 16 | 68,736 | **4,296** |\n\n検算: `18 × 3,371 = 60,678` / `17 × 3,789 = 64,413` / `20 × 4,296 = 85,920` / `16 × 4,296 = 68,736`。\n\n決定的なのは最後の 2 行。**同一 commit を異なる件数で投げて、1 件あたりの商が 4,296 で一致している。** 報告値が実トークンの合計であれば、4 件減らして商が変わらないためには除外された 4 件が全て同一トークン数である必要があり、偶然としては苦しい。\n\n## 推論\n\nエンドポイントは batch 内の入力を**最長のものに padding** し、消費コンテキストを `件数 × padding 後の長さ` として数えていると考えられる。\n\n```\ncharged = batch_size × max_over_inputs(tokens(input))\n```\n\nこれが正しければ、これまでの 3 回が効かなかった理由が全て説明される。合計をどれだけ正確に縛っても、課金式に合計は現れないため。\n\n**確からしさ**: 4 観測からの推論であり、確定ではない。確認方法は下記。\n\n## 確認方法\n\n同一内容の入力を件数だけ変えて投げ、報告値が件数に比例するかを見る。比例すれば padding モデルが確定する。小さな入力 1 件と大きな入力 1 件を混ぜた batch が、大きい方の 2 倍で課金されるかを見るのが最短。\n\n## 正しい境界の形\n\n```\nbatch_size × max_over_inputs(utf8ByteLength(input) + TOKEN_OVERHEAD_PER_INPUT) <= WORKERS_AI_BATCH_CONTEXT_LIMIT\n```\n\nトークン数の上界としてバイト数を使う点(#244)は維持する。破れていたのは上界そのものではなく、**合計を縛っていたこと**である。\n\n`1fb0f6b` で検算すると、最長入力が約 3,371 トークン相当なので 1 batch は 17 件まで。18 件で超えていた。\n\n## 設計上の帰結(合計軸には無かった性質)\n\n- **最大の入力が batch 全体の単価を決める。** 小さい入力を並べても安くならない。大きい入力が 1 件混ざれば、全件がその長さで課金される\n- したがって**サイズの近いものをまとめるほど効率が上がる**。極端に大きい 1 件は単独 batch にするのが最適\n- ただし現在の `planEmbeddingBatches` は連続範囲 `{start, end}` を返し、呼び出し側が files 配列を同じ境界で切ることで位置対応を保っている。サイズ順にまとめるには入力の並べ替えが必要で、この interface では表現できない。**範囲ではなく index 集合を返す形への変更が要るかどうかを判断すること**\n- 並べ替えを行わない素朴な実装でも上記の境界式は満たせる。効率と実装量の判断は実装側に委ねる\n\n## constraints\n\n- 合計軸の予算(`MAX_EMBEDDING_BATCH_BYTES` を合計に対して適用する形)は退役させる。合計軸を残したまま件数×最長を足すと、効かない条件が残る\n- `utf8ByteLength` と `TOKEN_OVERHEAD_PER_INPUT`(#244)は維持\n- 単独で上限を超える入力は 1 件の batch として送る。欠落させない、無限ループさせない\n- 入力順序と file 配列の位置対応は、並べ替えを行う場合も保証すること\n- **#240 の file 予算との整合を再検証する。** batch 数が変われば `DIFF_SUBREQUESTS_PER_FILE = 3` の前提(1 batch あたりの最小 file 数)が動く。#244 の時点で余裕は 75 中 74 まで詰まっている\n- 要件記述(`docs/0-requirements.md` / `docs/0-requirements.ja.md`)を同一 PR で更新する\n\n## target files\n\n- `src/pipeline/embedding.ts` — 境界式、必要なら planner の返り値形式\n- `src/pipeline/embed-diff.ts` — 並べ替えを行う場合の呼び出し側\n- `src/pipeline/embedding.test.ts` / `src/pipeline/embed-diff.test.ts`\n- `src/poller.ts` — `DIFF_SUBREQUESTS_PER_FILE` の前提が動く場合\n- `docs/0-requirements.md` / `docs/0-requirements.ja.md`\n\n## acceptance\n\n- `batch_size × max(入力コスト)` が上限を超えない\n- **`1fb0f6b`(20 file、うち 18 が indexable)と `92eb94d`(44 file)が embed に成功する**\n- `neuron-graph-rag` の forward watermark が `2026-08-11T15:33:02Z` を越えて前進する\n- 上記 4 観測を再現する回帰テスト(件数 × 最長で課金されることを前提にした fixture)\n- #240 の file 予算が破綻していない\n\n## 経緯\n\n#236(推定トークン合計)、#241 → #242(文字数合計)、#244(バイト数合計)に続く 4 度目の修正。前 3 回は「上界の取り方が実測より楽観」という同じ形の失敗だったが、本 issue はそれとは別で、**縛る量の選択そのものが誤っていた**という診断である。合計を縛る限り、上界をいくら厳しくしても課金式に届かない。\n\n#236 の受け入れ条件は一度も満たされていない。\n"
              },
              {
                "source_id": "T31S2",
                "repo": "Liplus-Project/github-rag-mcp",
                "title": "fix(pipeline): bound embed batches by UTF-8 byte count, not character count",
                "url": "https://github.com/Liplus-Project/github-rag-mcp/issues/244",
                "source_updated_at": "2026-08-14T16:23:38Z",
                "rerank_score": 0.1376933604478836,
                "state": "closed",
                "content_truncated": false,
                "excerpt": "fix(pipeline): bound embed batches by UTF-8 byte count, not character count\n\n## purpose\n\n`planEmbeddingBatches` の予算軸を UTF-16 code unit から **UTF-8 バイト数**へ移す。#241 が根拠にした `tokens <= chars` は成り立っておらず、実測で破れている。\n\n## observation(2026-08-15 00:30 JST cron、#242 deploy 後)\n\n```\nFailed to batch-embed diffs for Liplus-Project/neuron-graph-rag@92eb94dcb88c5e7494bc3b69377249e08601d99f\n  chunk offset 0: 3030: Max context reached 68736 tokens but model supports only 60000\n```\n\n| 項目 | 値 |\n|---|---|\n| file 数 | 16(#240 の file 予算により 44 から分割済み) |\n| batch | `chunk offset 0` のみ = 1 batch |\n| planner が課金した文字数 | <= 60,000(`MAX_EMBEDDING_BATCH_CHARS`) |\n| 実測 token | **68,736** |\n\nしたがって `tokens / chars >= 1.146`。**トークン数が文字数を超えている。**\n\n#242 が deploy されていることは確認済み: file 数が 44 -> 16 に変わり、token 実測値も過去(85,920 / 60,678 / 64,413)と異なる新しい値になっている。旧コードが動いている可能性は排除される。\n\n## 原因\n\n#241 / #242 が置いた前提はこれ。\n\n> every token of a BPE or SentencePiece vocabulary spans at least one character of the input\n> ⟹ tokens(input) <= input.length + SPECIAL_TOKENS_PER_INPUT\n\n**byte_fallback で破れる。** 語彙に無い文字は UTF-8 バイト列へ分解され、1 文字が複数 token になる。日本語 1 文字(3 バイト)は最大 3 token。実測の 1.146 倍という超過は、内容の一部がこの経路に落ちていることと整合する。\n\n## 方針:バイト数で縛る\n\n**1 token は最低 1 バイトを消費する。** byte_fallback が最も細かい分解であり、それ以下には割れない。したがって\n\n```\n1 batch の合計 UTF-8 バイト数 <= 60,000 - (special token 分)\n  ⟹ 合計 token 数 <= 60,000  (無条件に成立)\n```\n\n#241 が求めた「校正しない、構成上正しい」という性質を保ったまま、軸を 1 つ下げるだけで直る。文字数軸が満たせなかったのは、文字と token の対応が 1:1 以上であるという前提が偽だったためであり、バイトと token の対応にはその問題が無い。\n\nコスト: 日本語主体の入力では 1 文字 3 バイトのため、文字数軸に比べ約 3 倍保守的になる。batch 数が増える。これは正しさの代金として受け入れる。#240 の file 予算(`DIFF_SUBREQUESTS_PER_FILE = 3` は 1 batch あたり 3 file 以上を前提に amortised cost を見積もっている)との整合を確認すること。\n\n## constraints\n\n- 推定・校正の類を復活させない。バイト数は測定値であって推定ではない\n- `WORKERS_AI_BATCH_CONTEXT_LIMIT = 60000` は天井の記録として維持\n- special token の課金は入力ごと(#242 の判断を維持。batch の入力数に上限が無いため、一律予約では保証が成立しない)\n- 単独で予算を超える入力は 1 件の batch として送る。欠落させない、無限ループさせない\n- 入力順序の保持、input 配列と file 配列を同じ境界で切る契約は不変\n- **#240 の file 予算との整合を検証する。** 1 batch あたりの最小 file 数が下がるため、`DIFF_SUBREQUESTS_PER_FILE` の前提が崩れていないか確認し、崩れるなら同一 PR で調整する\n- 要件記述(`docs/0-requirements.md` / `docs/0-requirements.ja.md`)を同一 PR で更新する\n\n## target files\n\n- `src/pipeline/embedding.ts` — 予算軸をバイト数へ\n- `src/pipeline/embedding.test.ts` — 契約テストの更新、非 ASCII を含む回帰ケース\n- `src/pipeline/embed-diff.test.ts` — 分割ケースの期待値\n- `src/poller.ts` — `DIFF_SUBREQUESTS_PER_FILE` の前提が変わる場合\n- `docs/0-requirements.md` / `docs/0-requirements.ja.md`\n\n## acceptance\n\n- 1 batch の合計 UTF-8 バイト数が上限を超えない\n- **`1fb0f6b397c1ff333d698fe58a862b9583b463fe`(18 file)と `92eb94dcb88c5e7494bc3b69377249e08601d99f`(44 file)が embed に成功する**\n- `neuron-graph-rag` の forward watermark が `2026-08-11T15:33:02Z` を越えて前進する\n- 非 ASCII を含む実測相当(1 batch あたり 68,736 token 級)の回帰テストが追加されている\n- #240 の file 予算が破綻していない\n\n## 経緯\n\n#236(token 予算・推定器)、#238(subrequest / file 予算)、#241(文字数軸)に続く 4 周目。#236 の受け入れ条件「watermark が boundary commit を越える」は一度も満たされていない。3 回とも、境界の根拠が実測より楽観的だったことが原因である。今回はバイト数という測定可能な下界を使うため、同じ形での再発は起きない。\n"
              },
              {
                "source_id": "T31S3",
                "repo": "Liplus-Project/github-rag-mcp",
                "title": "enhancement: add cross-encoder reranker (bge-reranker-base) as 3rd retrieval tier",
                "url": "https://github.com/Liplus-Project/github-rag-mcp/issues/91",
                "source_updated_at": "2026-04-19T14:43:42Z",
                "rerank_score": 0.09936334937810898,
                "state": "closed",
                "content_truncated": false,
                "excerpt": "enhancement: add cross-encoder reranker (bge-reranker-base) as 3rd retrieval tier\n\n## 目的\n\nv0.6.x で導入した hybrid retrieval (Vectorize dense + D1 FTS5 sparse + RRF fusion) に **3 段目として cross-encoder reranker** を追加し、2026 production baseline (hybrid + reranker) に到達する。\n\n2026 業界標準で reranker は「optional の一段上」ではなく**production baseline の必須層**として位置付けられている。Cloudflare AI Search 公式 blog (2026-04-16) でも `@cf/baai/bge-reranker-base` を optional rerank 機能として組み込んでいる。Workers AI モデルとして呼び出せるため、DIY 経路でも実装可能。\n\n## 前提\n\n- Cloudflare Workers AI に `@cf/baai/bge-reranker-base` (cross-encoder reranker) が提供済\n- 呼び出し経路は既存の BGE-M3 embedding 呼び出しと同じ Workers AI primitive\n- Workers AI Free tier は 10,000 Neurons/day hard-stop。reranker 呼び出しは 1 query につき +1 Neuron 程度消費するため、既存 BGE-M3 embedding と合わせて neuron 消費が増える (運用観察要)\n- 現状の `search_issues` は `top_k` で最終件数を返しているが、reranker 導入後は overfetch (例: top_k × 5, max 50) → rerank → top_k trim のパターンになる (既存 labels/assignee post-filter の overfetch logic と同じ構造)\n- 参考: [Cloudflare AI Search agent primitive blog](https://blog.cloudflare.com/ai-search-agent-primitive/) / [hybrid search changelog](https://developers.cloudflare.com/changelog/post/2026-04-16-hybrid-search-and-relevance-boosting/)\n\n## 制約\n\n- **後方互換 non-breaking**: `search_issues` の既存インタフェースは変更しない。reranker は default ON だが opt-out option で無効化可能に (benchmarking / neuron 節約用)\n- Diff RAG の独自 schema 維持: reranker input は既存の `(query, candidate content)` pair なので Diff RAG との互換性は問題なし\n- reranker 呼び出しの input content 上限を確認・実装 (モデルの context window を超えないよう truncate)\n- Workers AI Free tier で運用可能な neuron 設計にする (overfetch 係数・default top_k を neuron 予算から逆算)\n- 実装スコープは `search_issues` のみ。`get_issue_context` / `list_recent_activity` は対象外 (これらは semantic search を直接使わないため)\n\n## 対象ファイル\n\n| ファイル | 変更内容 |\n|---|---|\n| `src/fts.ts` もしくは新規 `src/rerank.ts` | Workers AI `@cf/baai/bge-reranker-base` 呼び出し util、スコア統合ロジック |\n| `src/index.ts` / MCP tool 実装 | `search_issues` 内の retrieval path 拡張 (dense+sparse → RRF → overfetch → rerank → top_k) |\n| `wrangler.toml` | binding は既存 `env.AI` で流用、追加 binding なし |\n| `docs/0-requirements.{ja,md}` | Retrieval Model 節に reranker 追加、3 段構成図に更新 |\n| `README.md` / `README.ja.md` | Architecture 図に reranker を含む、最小差分 |\n\n## 未確定事項 (memo 段階、実装前に要確認)\n\n- reranker モデルの最新候補確認 (bge-reranker-base 以外に、2026 時点で Workers AI 上でより良いモデルが出ていないか)\n- overfetch 係数 (top_k × 5 or × 10 等) のデフォルト値\n- neuron 消費実測 (1 クエリあたりの embedding + rerank の neuron 数)\n- opt-out パラメータ名 (`rerank: false` が妥当か)\n\n## 関連\n\n- v0.6.0 PR #86: hybrid retrieval 基盤 (dense + sparse + RRF)\n- v0.6.1 PR #90: README マルチランゲージ反映\n- Cloudflare AI Search blog (2026-04-16): cross-encoder reranker の primitive 化事例\n"
              }
            ]
          },
          {
            "case_id": "T84",
            "question": "github-rag-mcp の埋め込み予算は全入力のUTF-8バイト数の合計を縛ればよいのですか",
            "retrieval_note": null,
            "sources": [
              {
                "source_id": "T84S1",
                "repo": "Liplus-Project/github-rag-mcp",
                "title": "fix(pipeline): bound embed batches by count times longest input, not by total",
                "url": "https://github.com/Liplus-Project/github-rag-mcp/issues/246",
                "source_updated_at": "2026-08-15T01:22:01Z",
                "rerank_score": 0.11567467451095581,
                "state": "closed",
                "content_truncated": false,
                "excerpt": "fix(pipeline): bound embed batches by count times longest input, not by total\n\n## purpose\n\nWorkers AI の batch embed が拒否する量は、入力の**合計**ではなく **`batch 件数 × batch 内の最長入力`** である可能性が高い。#236 / #241 / #244 は 3 回とも合計を縛っており、縛る対象そのものが違っていた。境界の形を変える。\n\n## observation\n\n`0411f101`(#244 の UTF-8 バイト版)が 8 時間前から 100% traffic で稼働中。それでも 2026-08-15 09:30 JST の cron で同じ失敗が出る。\n\n```\nFailed to batch-embed diffs for Liplus-Project/neuron-graph-rag@1fb0f6b397c1ff333d698fe58a862b9583b463fe\n  chunk offset 0: 3030: Max context reached 60678 tokens but model supports only 60000\n```\n\n18 file が `chunk offset 0` の 1 batch。そして **60,678 という報告値が #242 の前から一度も変わっていない**。推定トークン軸・文字数軸・バイト数軸の 3 つを通しても同一である以上、batch の組み方が変わっていないことになる。\n\n### 報告値を件数で割ると全て整数になる\n\n| commit | batch 件数 | 報告値 | 商 |\n|---|---|---|---|\n| `1fb0f6b397c1ff333d698fe58a862b9583b463fe` | 18 | 60,678 | **3,371** |\n| `bdf8b62bfc8cc88944d342ab0cefc1f544edfa5c` | 17 | 64,413 | **3,789** |\n| `92eb94dcb88c5e7494bc3b69377249e08601d99f` | 20 | 85,920 | **4,296** |\n| `92eb94dcb88c5e7494bc3b69377249e08601d99f` | 16 | 68,736 | **4,296** |\n\n検算: `18 × 3,371 = 60,678` / `17 × 3,789 = 64,413` / `20 × 4,296 = 85,920` / `16 × 4,296 = 68,736`。\n\n決定的なのは最後の 2 行。**同一 commit を異なる件数で投げて、1 件あたりの商が 4,296 で一致している。** 報告値が実トークンの合計であれば、4 件減らして商が変わらないためには除外された 4 件が全て同一トークン数である必要があり、偶然としては苦しい。\n\n## 推論\n\nエンドポイントは batch 内の入力を**最長のものに padding** し、消費コンテキストを `件数 × padding 後の長さ` として数えていると考えられる。\n\n```\ncharged = batch_size × max_over_inputs(tokens(input))\n```\n\nこれが正しければ、これまでの 3 回が効かなかった理由が全て説明される。合計をどれだけ正確に縛っても、課金式に合計は現れないため。\n\n**確からしさ**: 4 観測からの推論であり、確定ではない。確認方法は下記。\n\n## 確認方法\n\n同一内容の入力を件数だけ変えて投げ、報告値が件数に比例するかを見る。比例すれば padding モデルが確定する。小さな入力 1 件と大きな入力 1 件を混ぜた batch が、大きい方の 2 倍で課金されるかを見るのが最短。\n\n## 正しい境界の形\n\n```\nbatch_size × max_over_inputs(utf8ByteLength(input) + TOKEN_OVERHEAD_PER_INPUT) <= WORKERS_AI_BATCH_CONTEXT_LIMIT\n```\n\nトークン数の上界としてバイト数を使う点(#244)は維持する。破れていたのは上界そのものではなく、**合計を縛っていたこと**である。\n\n`1fb0f6b` で検算すると、最長入力が約 3,371 トークン相当なので 1 batch は 17 件まで。18 件で超えていた。\n\n## 設計上の帰結(合計軸には無かった性質)\n\n- **最大の入力が batch 全体の単価を決める。** 小さい入力を並べても安くならない。大きい入力が 1 件混ざれば、全件がその長さで課金される\n- したがって**サイズの近いものをまとめるほど効率が上がる**。極端に大きい 1 件は単独 batch にするのが最適\n- ただし現在の `planEmbeddingBatches` は連続範囲 `{start, end}` を返し、呼び出し側が files 配列を同じ境界で切ることで位置対応を保っている。サイズ順にまとめるには入力の並べ替えが必要で、この interface では表現できない。**範囲ではなく index 集合を返す形への変更が要るかどうかを判断すること**\n- 並べ替えを行わない素朴な実装でも上記の境界式は満たせる。効率と実装量の判断は実装側に委ねる\n\n## constraints\n\n- 合計軸の予算(`MAX_EMBEDDING_BATCH_BYTES` を合計に対して適用する形)は退役させる。合計軸を残したまま件数×最長を足すと、効かない条件が残る\n- `utf8ByteLength` と `TOKEN_OVERHEAD_PER_INPUT`(#244)は維持\n- 単独で上限を超える入力は 1 件の batch として送る。欠落させない、無限ループさせない\n- 入力順序と file 配列の位置対応は、並べ替えを行う場合も保証すること\n- **#240 の file 予算との整合を再検証する。** batch 数が変われば `DIFF_SUBREQUESTS_PER_FILE = 3` の前提(1 batch あたりの最小 file 数)が動く。#244 の時点で余裕は 75 中 74 まで詰まっている\n- 要件記述(`docs/0-requirements.md` / `docs/0-requirements.ja.md`)を同一 PR で更新する\n\n## target files\n\n- `src/pipeline/embedding.ts` — 境界式、必要なら planner の返り値形式\n- `src/pipeline/embed-diff.ts` — 並べ替えを行う場合の呼び出し側\n- `src/pipeline/embedding.test.ts` / `src/pipeline/embed-diff.test.ts`\n- `src/poller.ts` — `DIFF_SUBREQUESTS_PER_FILE` の前提が動く場合\n- `docs/0-requirements.md` / `docs/0-requirements.ja.md`\n\n## acceptance\n\n- `batch_size × max(入力コスト)` が上限を超えない\n- **`1fb0f6b`(20 file、うち 18 が indexable)と `92eb94d`(44 file)が embed に成功する**\n- `neuron-graph-rag` の forward watermark が `2026-08-11T15:33:02Z` を越えて前進する\n- 上記 4 観測を再現する回帰テスト(件数 × 最長で課金されることを前提にした fixture)\n- #240 の file 予算が破綻していない\n\n## 経緯\n\n#236(推定トークン合計)、#241 → #242(文字数合計)、#244(バイト数合計)に続く 4 度目の修正。前 3 回は「上界の取り方が実測より楽観」という同じ形の失敗だったが、本 issue はそれとは別で、**縛る量の選択そのものが誤っていた**という診断である。合計を縛る限り、上界をいくら厳しくしても課金式に届かない。\n\n#236 の受け入れ条件は一度も満たされていない。\n"
              },
              {
                "source_id": "T84S2",
                "repo": "Liplus-Project/github-rag-mcp",
                "title": "fix(pipeline): bound embed batches by UTF-8 byte count, not character count",
                "url": "https://github.com/Liplus-Project/github-rag-mcp/issues/244",
                "source_updated_at": "2026-08-14T16:23:38Z",
                "rerank_score": 0.05751528590917587,
                "state": "closed",
                "content_truncated": false,
                "excerpt": "fix(pipeline): bound embed batches by UTF-8 byte count, not character count\n\n## purpose\n\n`planEmbeddingBatches` の予算軸を UTF-16 code unit から **UTF-8 バイト数**へ移す。#241 が根拠にした `tokens <= chars` は成り立っておらず、実測で破れている。\n\n## observation(2026-08-15 00:30 JST cron、#242 deploy 後)\n\n```\nFailed to batch-embed diffs for Liplus-Project/neuron-graph-rag@92eb94dcb88c5e7494bc3b69377249e08601d99f\n  chunk offset 0: 3030: Max context reached 68736 tokens but model supports only 60000\n```\n\n| 項目 | 値 |\n|---|---|\n| file 数 | 16(#240 の file 予算により 44 から分割済み) |\n| batch | `chunk offset 0` のみ = 1 batch |\n| planner が課金した文字数 | <= 60,000(`MAX_EMBEDDING_BATCH_CHARS`) |\n| 実測 token | **68,736** |\n\nしたがって `tokens / chars >= 1.146`。**トークン数が文字数を超えている。**\n\n#242 が deploy されていることは確認済み: file 数が 44 -> 16 に変わり、token 実測値も過去(85,920 / 60,678 / 64,413)と異なる新しい値になっている。旧コードが動いている可能性は排除される。\n\n## 原因\n\n#241 / #242 が置いた前提はこれ。\n\n> every token of a BPE or SentencePiece vocabulary spans at least one character of the input\n> ⟹ tokens(input) <= input.length + SPECIAL_TOKENS_PER_INPUT\n\n**byte_fallback で破れる。** 語彙に無い文字は UTF-8 バイト列へ分解され、1 文字が複数 token になる。日本語 1 文字(3 バイト)は最大 3 token。実測の 1.146 倍という超過は、内容の一部がこの経路に落ちていることと整合する。\n\n## 方針:バイト数で縛る\n\n**1 token は最低 1 バイトを消費する。** byte_fallback が最も細かい分解であり、それ以下には割れない。したがって\n\n```\n1 batch の合計 UTF-8 バイト数 <= 60,000 - (special token 分)\n  ⟹ 合計 token 数 <= 60,000  (無条件に成立)\n```\n\n#241 が求めた「校正しない、構成上正しい」という性質を保ったまま、軸を 1 つ下げるだけで直る。文字数軸が満たせなかったのは、文字と token の対応が 1:1 以上であるという前提が偽だったためであり、バイトと token の対応にはその問題が無い。\n\nコスト: 日本語主体の入力では 1 文字 3 バイトのため、文字数軸に比べ約 3 倍保守的になる。batch 数が増える。これは正しさの代金として受け入れる。#240 の file 予算(`DIFF_SUBREQUESTS_PER_FILE = 3` は 1 batch あたり 3 file 以上を前提に amortised cost を見積もっている)との整合を確認すること。\n\n## constraints\n\n- 推定・校正の類を復活させない。バイト数は測定値であって推定ではない\n- `WORKERS_AI_BATCH_CONTEXT_LIMIT = 60000` は天井の記録として維持\n- special token の課金は入力ごと(#242 の判断を維持。batch の入力数に上限が無いため、一律予約では保証が成立しない)\n- 単独で予算を超える入力は 1 件の batch として送る。欠落させない、無限ループさせない\n- 入力順序の保持、input 配列と file 配列を同じ境界で切る契約は不変\n- **#240 の file 予算との整合を検証する。** 1 batch あたりの最小 file 数が下がるため、`DIFF_SUBREQUESTS_PER_FILE` の前提が崩れていないか確認し、崩れるなら同一 PR で調整する\n- 要件記述(`docs/0-requirements.md` / `docs/0-requirements.ja.md`)を同一 PR で更新する\n\n## target files\n\n- `src/pipeline/embedding.ts` — 予算軸をバイト数へ\n- `src/pipeline/embedding.test.ts` — 契約テストの更新、非 ASCII を含む回帰ケース\n- `src/pipeline/embed-diff.test.ts` — 分割ケースの期待値\n- `src/poller.ts` — `DIFF_SUBREQUESTS_PER_FILE` の前提が変わる場合\n- `docs/0-requirements.md` / `docs/0-requirements.ja.md`\n\n## acceptance\n\n- 1 batch の合計 UTF-8 バイト数が上限を超えない\n- **`1fb0f6b397c1ff333d698fe58a862b9583b463fe`(18 file)と `92eb94dcb88c5e7494bc3b69377249e08601d99f`(44 file)が embed に成功する**\n- `neuron-graph-rag` の forward watermark が `2026-08-11T15:33:02Z` を越えて前進する\n- 非 ASCII を含む実測相当(1 batch あたり 68,736 token 級)の回帰テストが追加されている\n- #240 の file 予算が破綻していない\n\n## 経緯\n\n#236(token 予算・推定器)、#238(subrequest / file 予算)、#241(文字数軸)に続く 4 周目。#236 の受け入れ条件「watermark が boundary commit を越える」は一度も満たされていない。3 回とも、境界の根拠が実測より楽観的だったことが原因である。今回はバイト数という測定可能な下界を使うため、同じ形での再発は起きない。\n"
              },
              {
                "source_id": "T84S3",
                "repo": "Liplus-Project/github-rag-mcp",
                "title": "fix(poller): cap per-commit file count in the diff path against the subrequest budget",
                "url": "https://github.com/Liplus-Project/github-rag-mcp/issues/238",
                "source_updated_at": "2026-08-14T07:19:55Z",
                "rerank_score": 0.04301812872290611,
                "state": "closed",
                "content_truncated": false,
                "excerpt": "fix(poller): cap per-commit file count in the diff path against the subrequest budget\n\n## purpose\n\ndiff path に per-commit の file 上限が無く、file 数の多い commit が単独で Worker の 1 invocation あたり subrequest 予算(1000)に迫りうる。#236 が閉じた token 軸と同じ形で diff surface が恒久停止する経路なので、file 数軸にも上限を入れる。\n\n## premise\n\n`Too many subrequests by single Worker invocation` は仮説ではなく、この worker の production で現に発生している(#236 本文の観測、および wiki 取得経路 `fetchWikiContent`)。\n\nper-file のコストは `src/pipeline/embed-diff.ts` で 2 subrequest。\n\n- `upsertFtsRow`(D1 FTS mirror)— L235\n- `storeStub.fetch`(Durable Object への DiffRecord 記録)— L295\n\nこれに batch 単位のコストが加わる。1 batch あたり 2 subrequest(Workers AI call と `VECTORIZE.upsert`)。GitHub の commit detail API は 1 commit あたり最大 300 file を返す。\n\n`src/poller.ts` の cap は **commit 数**にしか掛かっていない。\n\n- `MAX_DIFF_COMMITS_FORWARD_PER_RUN = 5`\n- `MAX_DIFF_COMMITS_BACKWARD_PER_RUN = 5`\n\nfile 数側の cap は diff path のどこにも存在しない。しかも cron 1 tick は 1 invocation で全 repo・全 surface を処理するため、subrequest 予算は docs / wiki / issue / release 経路と共有されている。\n\n## なぜ stall するか\n\n#178 の watermark 不変条件により、取り込みに成功していない commit を watermark は追い越さない。subrequest 枯渇で file の upsert が失敗すると `failed` に計上され、その commit は未取り込みとして扱われる。file 数が原因である以上、次の cron でも同じ commit が同じ file 数で再試行されるので、失敗は決定論的。#236 で修正した token 軸とまったく同じ停止の形になる。\n\n不変条件側は正しい。上限を持たない側が欠陥である。\n\n## constraints\n\n- watermark 不変条件は変更しない\n- file を落とさない。上限は「1 run で処理する file 数」の分割であって、間引きではない。1 commit を複数 run にまたがって処理する場合、その commit の watermark は完了まで前進させない(不変条件と整合させる)\n- subrequest 予算は invocation 全体で共有されているため、diff path だけの局所最適にしない。少なくとも「diff path が予算をどれだけ使ってよいか」を明示する形にする\n- 要件記述(`docs/0-requirements.md` / `docs/0-requirements.ja.md`)を同一 PR で更新する\n\n## target files\n\n- `src/poller.ts` — per-commit file 上限と、部分処理時の watermark 保持\n- `src/pipeline/embed-diff.ts` — 呼び出し側の分割受け入れ\n- `docs/0-requirements.md` / `docs/0-requirements.ja.md` — Diff Pipeline 節\n- テスト — 上限超過 commit が分割され、完了まで watermark が前進しないこと\n\n## acceptance\n\n- file 数の多い commit が単独で invocation 予算を使い切らない\n- 部分処理された commit の watermark が前進しない\n- 既存テストが通り、回帰テストが追加されている\n\n## 経緯\n\n#236 の実装中に 2 回にわたり報告された隣接ギャップ。#236 の literal 外のため分離した。\n"
              }
            ]
          },
          {
            "case_id": "T62",
            "question": "github-rag-mcp の wiki グラフは参照の mention を保存するのか、supersedes という意味の関係を分類しているのか",
            "retrieval_note": null,
            "sources": [
              {
                "source_id": "T62S1",
                "repo": "Liplus-Project/neuron-graph-rag",
                "title": "corpora/github-retrieval-parity-v4/docs/Decision-Structure.md",
                "url": "https://github.com/Liplus-Project/neuron-graph-rag/blob/main/corpora/github-retrieval-parity-v4/docs/Decision-Structure.md",
                "source_updated_at": "2026-09-08T18:03:02.924Z",
                "rerank_score": 0.10445662587881088,
                "state": "active",
                "content_truncated": true,
                "excerpt": "corpora/github-retrieval-parity-v4/docs/Decision-Structure.md\n\n# 判断構造レイヤー(Decision Structure)\n\n判断構造レイヤーは、要求仕様書(1-6)やユーザー向けドキュメント(A-D)とは異なる第三の用途を持つ。\n**実体エントリ(`<topic>.md` 形式の kebab-case ファイル名)は GitHub Wiki に格納される**。本ファイル(`docs/Decision-Structure.md`)はそのレイヤーの運用仕様としての index に専属する。\n\n---\n\n## 位置づけ\n\nモデルレイヤー仕様書(1.-Model.md)は外部記憶を次のように定義している:\n\n> issue、docs、commit message は判断の履歴と根拠の外部記憶として機能する。\n> 外部記憶が記録するのは判断であり、一次情報ではない。\n\n判断構造レイヤーは、この外部記憶の原則に基づく。\nセッションをまたぐと消える判断知を蓄積する。\n\n**履歴 (log) ではなく構造 (structure) である**: Decision Structure は時間順 append-only の log ではない。判断ノード (state 形エントリ) と supersede / depend / conflict edge による意味グラフであり、volume は refine / replace で安定する。維持運用は refactor (normal operation) として扱う。\n\n実体エントリは GitHub Wiki にあり、`github-rag-mcp >= v0.8.5` の wiki indexing 経由で RAG-MCP のセマンティック検索対象に入る(書くだけで検索される)。\n\n書き味は wiki の casual write(PR ceremony 不要、git push 直接)に乗る。仕様書(1-6 / A-D)の write は重い PR フローに残し、判断構造の write は軽量に保つ非対称設計。\n\n`docs/Decision-Structure.md`(本ファイル)はレイヤー運用仕様の固定 index として docs/ 側に残し、`adapter/claude/hooks/on-session-start.sh` が cold-start synthesis material として head を emit する経路を維持する。\n\n---\n\n## 蓄積条件(いつ書くか)\n\n以下のいずれかに該当するとき、判断構造を wiki に追記または新規作成する:\n\n- 設計上の分岐で選択肢を比較し、理由をもって一方を選んだとき\n- アプローチを試して失敗し、原因が判明したとき\n- 前提を検証し、結果が確定したとき(成功・失敗を問わない)\n- 複数セッションにわたって同じ調査を繰り返していることに気づいたとき\n\n書かないもの:\n- 時間で変わる事実(API仕様、ライブラリのバージョン挙動)→ 鮮度問題があるため都度調査する\n- issue や commit body に既に書かれている判断 → 重複を避ける\n- 自明な選択(選択肢が実質一つしかないもの)\n\n---\n\n## エントリ shape (state-form 推奨)\n\n新規エントリは state 形で記述する:\n\n- **Question** = どの問いに対する判断か\n- **Current resolution** = 現在の答え (state、現在形)\n- **Edges** = supersede / depend / conflict edge の宣言\n\nstate 形は時間順 implicit ordering ではなく現在 state を主語にする。判断は時間とともに refine / replace されるため、最新 state が「今どう判断しているか」を直接表すほうが読み手に効く。詳細は `skills/evolution-decision-structure-write/SKILL.md` を参照。\n\n既存エントリは遡及書き換えしない。新規エントリと既存 entry の意味更新時に state 形を用いる(forward guidance)。\n\n---\n\n## Edge taxonomy (primary edge vocabulary)\n\nstate 形エントリは適用可能な edge を declare することが推奨される。primary edge は 3 種:\n\n- **supersedes** = この判断は別 entry の判断を置き換える。旧 entry は graph に残る(削除しない)が、検索路は最新 entry に集まる\n- **depends on** = この判断は別 entry の判断を前提とする。前提が崩れた場合は本判断も再評価対象になる\n- **conflicts with** = この判断は別 entry の判断と一部または全体で矛盾する。未解決の論点を可視化する surface\n\nedge は前方リンク(本 entry から相手 entry へのリンク)として書く。逆方向のリンクは次回 wiki sync の cross-reference integrity check で整合性が観測される。\n\n---\n\n## 検索のタイミング(いつ読まれるか)\n\n判断構造に専用のトリガーは設けない。\n`mcp__github-rag-mcp__search` のセマンティック検索を `type: \"wiki_doc\"` または `\"all\"` で叩いた際に自然に引っかかる。\n\n主な検索機会:\n\n- issue の forming → ready 移行時に前提を検証するとき\n- 新しい設計判断を行う前に、過去の類似判断を探すとき\n- `skills/model-agentic-search/SKILL.md` の探索 trigger 発火 (governance + mechanical core 統合) に基づく情報収集の一環として\n\n---\n\n## メンテナンス (refactor framing)\n\n判断構造は構造体である。削除や統合は「履歴を消すこと」ではなく「構造を refactor すること」として normal operation の中に位置づける。\n\n**supersede via link を上書きより positive default として優先する**。既存 entry が無効化された場合、旧 entry を削除するのではなく新 entry を立て、旧 entry に supersede edge を張る。検索路は最新 entry に集まりつつ、graph 構造は維持される。\n\n削除条件(条件に該当する場合のみ):\n\n- 前提が変わり、記録された判断の根拠が無効になったとき\n- 対象の機能やコードが削除され、判断自体が無意味になったとき\n- 要求仕様書に統合され、独立した記録として残す必要がなくなったとき\n\nこれらは「履歴を抹消する」ではなく「structure が更新された結果として旧ノードを撤去する」操作である。条件未充足の状態で「念のため消す」ことはしない。\n\nwiki 上のファイルは git history に残るので、削除しても reflog 経由で復元可能。\n\nタイトル(ファイル名)の変更も自由化されている。整理整頓の一環としてエントリ名を rename する場合は、`git mv old-slug.md new-slug.md` + 全 entry の cross-reference 追従 + `_Sidebar.md` の slug 更新 + 本 index 表の更新を 1 コミットで行う。broken cross-reference は `skills/operations-on-wiki-sync/SKILL.md` の Cross-reference integrity assertion が次回 wiki sync で検出する。\n\n---\n\n## ファイル命名と所在\n\n| ファイル | 所在 | 用途 |\n|----------|------|------|\n| `Decision-Structure.md` | docs/ + wiki | レイヤー運用仕様(本ファイル)。docs/ は cold-start hook 用、wiki は nav 用 |\n| `<topic>.md` | wiki のみ | 個別の判断構造(kebab-case トピック名、prefix なし) |\n\nファイル名は **kebab-case のトピック名のみ**(例: `wiki-sync-sidebar-integrity-check.md`)。順序を示す prefix は付けない。理由は以下:\n\n- 26 字上限の構造的天井を取り除く\n- トピックの整理整頓(rename / restructure)を自由化する\n- filesystem 順序ではなく本 index と `_Sidebar.md` で順序を明示する\n\nwiki 内の閲覧は wiki sidebar の「判断構造」セクション、または `mcp__github-rag-mcp__search` の `type: \"wiki_doc\"` 経由。\n\n---\n\n## 既存エントリ一覧\n\n| ファイル | 主題 |\n|----------|------|\n| [`layer-reorg-rationale`](https://github.com/Liplus-Project/liplus-language/wiki/layer-reorg-rationale) | L1-L6 レイヤー再編の意図と、L5/L6 に rules/ サブディレクトリが無い理由 |\n| [`github-app-user-to-server-token-expiration`](https://github.com/Liplus-Project/liplus-language/wiki/github-app-user-to-server-token-expiration) | GitHub App の User-to-server token expiration 地雷と Opt-out 判断 |\n| [`sheepdog-engineering-concept`](https://github.com/Liplus-Project/liplus-language/wiki/sheepdog-engineering-concept) | シープドッグエンジニアリング命名と思想の確定(ハーネスの先) |\n| [`prerelease-tag-recovery-procedure`](https://github.com/Liplus-Project/liplus-language/wiki/prerelease-tag-recovery-procedure) | 「プレリリースタグ」解釈と release 復元手順 |\n| [`release-flip-drift-patterns`](https://github.com/Liplus-Project/liplus-language/wiki/release-flip-drift-patterns) | release / Latest flip 時の過剰拡張・過剰委縮 drift パターン spec 補助記録 |\n| [`li-plus-long-term-vision-feedback-only`](https://github.com/Liplus-Project/liplus-language/wiki/li-plus-long-term-vision-feedback-only) | Li+ 長期 vision(human 明言「フィードバックだけで」)と event-driven substrate |\n| [`master-role-as-client-architect`](https://github.com/Liplus-Project/liplus-language/wiki/master-role-as-client-architect) | human の役割 = client + architect、programmer は AI(git author ≠ content author) |\n| [`current-architecture-as-concession`](https://github.com/Liplus-Project/liplus-language/wiki/current-architecture-as-concession) | 現行アーキテクチャは譲歩 — Claude Code 特化 + 責務分割の経緯 |\n| [`li-plus-license-apache-2-rationale`](https://github.com/Liplus-Project/liplus-language/wiki/li-plus-license-apache-2-rationale) | Li+ license が Apache-2.0 である理由 — prompt artifact を license 対象に明示包摂 |\n| [`character-instance-evolution-history`](https://github.com/Liplus-Project/liplus-language/wiki/character-instance-evolution-history) | Character_Instance 進化史 + Rejected path(programmer/tester)+ pairing 原則 + 双方向制約 |\n| [`prompt-as-emotion-vector-controller`](https://github.com/Liplus-Project/liplus-language/wiki/prompt-as-emotion-vector-controller) | prompt = 感情ベクトル controller、Li+ rules は emotion vector engineering |\n| [`agentic-search-five-phase-refactor`](https://github.com/Liplus-Project/liplus-language/wiki/agentic-search-five-phase-refactor) | agentic-search 5-phase refactor — skill encapsulation と内部知識の比較基線化 |\n| [`character-instance-output-styles-migration`](https://github.com/Liplus-Project/liplus-language/wiki/character-instance-output-styles-migration) | Character_Instance loading mechanism を rules slot から output-styles slot に移行 (Claude adapter) |\n| [`li-plus-lightening-l1-gate-override`](https://github.com/Liplus-Project/liplus-language/wiki/li-plus-lightening-l1-gate-override) | Li+ lightening 文脈での L1 gate override 判断 |\n| [`subagent-state-machine-label-mechanism`](https://github.com/Liplus-Project/liplus-language/wiki/subagent-state-machine-label-mechanism) | subagent state-machine label 機構導入判断 (in-progress / review-pending / waiting / blocked + 部分 label 権限) |\n| [`lsp-integration-out-of-scope`](https://github.com/Liplus-Project/liplus-language/wiki/lsp-integration-out-of-scope) | LSP 統合は Li+ スコープ外 — 言語ごと常駐サーバ重量と汎用 harness 原則の衝突 |\n| [`character-instance-opt-in-and-surface-scope`](https://github.com/Liplus-Project/liplus-language/wiki/character-instance-opt-in-and-surface-scope) | Character_Instance を opt-in configuration + surface scope に refactor — universal binding 解消、subagent hollow prefix bug 構造的解消 |\n| [`bootstrap-walkthrough-skip-and-gh-install-relocation`](https://github.com/Liplus-Project/liplus-language/wiki/bootstrap-walkthrough-skip-and-gh-install-relocation) | bootstrap walkthrough を 3 軸 AND gate (sentinel tag / schema / language) で skip 可能化 + gh install を hook 側に移譲(context 約 4% 削減、`Li+configを実行` magic phrase で強制再走) |\n| [`parallel-subagent-eval-three-axis-decomposition`](https://github.com/Liplus-Project/liplus-language/wiki/parallel-subagent-eval-three-axis-decomposition) | parallel-subagent-eval を三軸(subagent_count × axes_per_subagent × pr"
              },
              {
                "source_id": "T62S2",
                "repo": "Liplus-Project/liplus-language",
                "title": "docs/Decision-Structure.md",
                "url": "https://github.com/Liplus-Project/liplus-language/blob/main/docs/Decision-Structure.md",
                "source_updated_at": "2026-10-12T12:02:03.499Z",
                "rerank_score": 0.09515295177698135,
                "state": "active",
                "content_truncated": true,
                "excerpt": "docs/Decision-Structure.md\n\n# 判断構造レイヤー(Decision Structure)\n\n判断構造レイヤーは、要求仕様書(1-6)やユーザー向けドキュメント(A-D)とは異なる第三の用途を持つ。\n**実体エントリ(`<topic>.md` 形式の kebab-case ファイル名)は GitHub Wiki に格納される**。本ファイル(`docs/Decision-Structure.md`)はそのレイヤーの運用仕様としての index に専属する。\n\n---\n\n## 位置づけ\n\nモデルレイヤー仕様書(1.-Model.md)は外部記憶を次のように定義している:\n\n> issue、docs、commit message は判断の履歴と根拠の外部記憶として機能する。\n> 外部記憶が記録するのは判断であり、一次情報ではない。\n\n判断構造レイヤーは、この外部記憶の原則に基づく。\nセッションをまたぐと消える判断知を蓄積する。\n\n**履歴 (log) ではなく構造 (structure) である**: Decision Structure は時間順 append-only の log ではない。判断ノード (state 形エントリ) と supersede / depend / conflict edge による意味グラフであり、volume は refine / replace で安定する。維持運用は refactor (normal operation) として扱う。\n\n実体エントリは GitHub Wiki にあり、`github-rag-mcp >= v0.8.5` の wiki indexing 経由で RAG-MCP のセマンティック検索対象に入る(書くだけで検索される)。\n\n書き味は wiki の casual write(PR ceremony 不要、git push 直接)に乗る。仕様書(1-6 / A-D)の write は重い PR フローに残し、判断構造の write は軽量に保つ非対称設計。\n\n`docs/Decision-Structure.md`(本ファイル)はレイヤー運用仕様の固定 index として docs/ 側に残し、`adapter/claude/hooks/on-session-start.sh` が cold-start synthesis material として head を emit する経路を維持する。\n\n---\n\n## 蓄積条件(いつ書くか)\n\n以下のいずれかに該当するとき、判断構造を wiki に追記または新規作成する:\n\n- 設計上の分岐で選択肢を比較し、理由をもって一方を選んだとき\n- アプローチを試して失敗し、原因が判明したとき\n- 前提を検証し、結果が確定したとき(成功・失敗を問わない。ただし self-evolution observation entry の `settle` は、置き場所を `skills/evolution-observation-entry/SKILL.md` に従って選ぶ)\n- 複数セッションにわたって同じ調査を繰り返していることに気づいたとき\n\n書かないもの:\n- 時間で変わる事実(API仕様、ライブラリのバージョン挙動)→ 鮮度問題があるため都度調査する\n- issue や commit body に既に書かれている判断 → 重複を避ける\n- 自明な選択(選択肢が実質一つしかないもの)\n\n---\n\n## エントリ shape (state-form 推奨)\n\n新規エントリは state 形で記述する:\n\n- **Question** = どの問いに対する判断か\n- **Current resolution** = 現在の答え (state、現在形)\n- **Edges** = supersede / depend / conflict edge の宣言\n\nstate 形は時間順 implicit ordering ではなく現在 state を主語にする。判断は時間とともに refine / replace されるため、最新 state が「今どう判断しているか」を直接表すほうが読み手に効く。詳細は `skills/evolution-decision-structure-write/SKILL.md` を参照。\n\n既存エントリは遡及書き換えしない。新規エントリと既存 entry の意味更新時に state 形を用いる(forward guidance)。\n\n---\n\n## 書く前の振り分け(対象リポジトリと要件仕様)\n\n本文を書く前に、二つの問いで書く内容を振り分ける。\n\n- **誰の判断か**:判断記録(Question / Current resolution / 根拠 / Edges)は、どのリポジトリについての判断であっても本 wiki の Decision Structure に置く。判断グラフは単一に保ち、リポジトリごとに分けない。entry を持つ wiki のリポジトリ以外が対象の判断では、本文冒頭に `Target repository: <owner>/<repo>` を 1 行で明記する\n- **判断記録か要件仕様か**:実装が満たすべき条件(契約・順序・データ形・success oracle など)は要件仕様である。entry には書かず、対象リポジトリの `docs/` に置き(docs/ が正本、`rules/operations/operations.md`)、entry からそこへリンクする。対象リポジトリの `docs/` にまだ無いときは、そのリポジトリに追加の issue を立て、entry からはその issue にリンクする\n\n振り分けは今回の書き込みが加える内容に適用する。既存 entry を掃き出して一括移動することはしない。手順は `skills/evolution-decision-structure-write/SKILL.md` の Procedure を参照。\n\n---\n\n## Edge taxonomy (primary edge vocabulary)\n\nstate 形エントリは適用可能な edge を declare することが推奨される。primary edge は 3 種:\n\n- **supersedes** = この判断は別 entry の判断を置き換える。旧 entry は graph に残る(削除しない)が、検索路は最新 entry に集まる\n- **depends on** = この判断は別 entry の判断を前提とする。前提が崩れた場合は本判断も再評価対象になる\n- **conflicts with** = この判断は別 entry の判断と一部または全体で矛盾する。未解決の論点を可視化する surface\n\nedge は前方リンク(本 entry から相手 entry へのリンク)として書く。逆方向のリンクは次回 wiki sync の cross-reference integrity check で整合性が観測される。\n\n---\n\n## 検索のタイミング(いつ読まれるか)\n\n判断構造に専用のトリガーは設けない。\n`mcp__github-rag-mcp__search` のセマンティック検索を `type: \"wiki_doc\"` または `\"all\"` で叩いた際に自然に引っかかる。\n\n主な検索機会:\n\n- issue の forming → ready 移行時に前提を検証するとき\n- 新しい設計判断を行う前に、過去の類似判断を探すとき\n- `skills/model-agentic-search/SKILL.md` の探索 trigger 発火 (governance + mechanical core 統合) に基づく情報収集の一環として\n\n---\n\n## メンテナンス (refactor framing)\n\n判断構造は構造体である。削除や統合は「履歴を消すこと」ではなく「構造を refactor すること」として normal operation の中に位置づける。\n\n**supersede via link を上書きより positive default として優先する**。既存 entry が無効化された場合、旧 entry を削除するのではなく新 entry を立て、旧 entry に supersede edge を張る。検索路は最新 entry に集まりつつ、graph 構造は維持される。\n\n削除条件(条件に該当する場合のみ):\n\n- 前提が変わり、記録された判断の根拠が無効になったとき\n- 対象の機能やコードが削除され、判断自体が無意味になったとき\n- 要求仕様書に統合され、独立した記録として残す必要がなくなったとき\n\nこれらは「履歴を抹消する」ではなく「structure が更新された結果として旧ノードを撤去する」操作である。条件未充足の状態で「念のため消す」ことはしない。\n\nwiki 上のファイルは git history に残るので、削除しても reflog 経由で復元可能。\n\nタイトル(ファイル名)の変更も自由化されている。整理整頓の一環としてエントリ名を rename する場合は、`git mv old-slug.md new-slug.md` + 全 entry の cross-reference 追従 + `_Sidebar.md` の slug 更新 + 本 index 表の更新を 1 コミットで行う。broken cross-reference は `skills/operations-on-wiki-sync/SKILL.md` の Cross-reference integrity assertion が次回 wiki sync で検出する。\n\n---\n\n## ファイル命名と所在\n\n| ファイル | 所在 | 用途 |\n|----------|------|------|\n| `Decision-Structure.md` | docs/ + wiki | レイヤー運用仕様(本ファイル)。docs/ は cold-start hook 用、wiki は nav 用 |\n| `<topic>.md` | wiki のみ | 個別の判断構造(kebab-case トピック名、prefix なし) |\n\nファイル名は **kebab-case のトピック名のみ**(例: `wiki-sync-sidebar-integrity-check.md`)。順序を示す prefix は付けない。理由は以下:\n\n- 26 字上限の構造的天井を取り除く\n- トピックの整理整頓(rename / restructure)を自由化する\n- filesystem 順序ではなく本 index と `_Sidebar.md` で順序を明示する\n\nwiki 内の閲覧は wiki sidebar の「判断構造」セクション、または `mcp__github-rag-mcp__search` の `type: \"wiki_doc\"` 経由。\n\n---\n\n## 既存エントリ一覧\n\n| ファイル | 主題 |\n|----------|------|\n| [`layer-reorg-rationale`](https://github.com/Liplus-Project/liplus-language/wiki/layer-reorg-rationale) | L1-L6 レイヤー再編の意図と、L5/L6 に rules/ サブディレクトリが無い理由 |\n| [`github-app-user-to-server-token-expiration`](https://github.com/Liplus-Project/liplus-language/wiki/github-app-user-to-server-token-expiration) | GitHub App の User-to-server token expiration 地雷と Opt-out 判断 |\n| [`sheepdog-engineering-concept`](https://github.com/Liplus-Project/liplus-language/wiki/sheepdog-engineering-concept) | シープドッグエンジニアリング命名と思想の確定(ハーネスの先) |\n| [`prerelease-tag-recovery-procedure`](https://github.com/Liplus-Project/liplus-language/wiki/prerelease-tag-recovery-procedure) | 「プレリリースタグ」解釈と release 復元手順 |\n| [`release-flip-drift-patterns`](https://github.com/Liplus-Project/liplus-language/wiki/release-flip-drift-patterns) | release / Latest flip 時の過剰拡張・過剰委縮 drift パターン spec 補助記録 |\n| [`li-plus-long-term-vision-feedback-only`](https://github.com/Liplus-Project/liplus-language/wiki/li-plus-long-term-vision-feedback-only) | Li+ 長期 vision(human 明言「フィードバックだけで」)と event-driven substrate |\n| [`master-role-as-client-architect`](https://github.com/Liplus-Project/liplus-language/wiki/master-role-as-client-architect) | human の役割 = client + architect、programmer は AI(git author ≠ content author) |\n| [`current-architecture-as-concession`](https://github.com/Liplus-Project/liplus-language/wiki/current-architecture-as-concession) | 現行アーキテクチャは譲歩 — Claude Code 特化 + 責務分割の経緯 |\n| [`li-plus-license-apache-2-rationale`](https://github.com/Liplus-Project/liplus-language/wiki/li-plus-license-apache-2-rationale) | Li+ license が Apache-2.0 である理由 — prompt artifact を license 対象に明示包摂 |\n| [`character-instance-evolution-history`](https://github.com/Liplus-Project/liplus-language/wiki/character-instance-evolution-history) | Character_Instance 進化史 + Rejected path(programmer/tester)+ pairing 原則 + 双方向制約 |\n| [`prompt-as-emotion-vector-controller`](https://github.com/Liplus-Project/liplus-language/wiki/prompt-as-emotion-vector-controller) | prompt = 感情ベクトル controller、Li+ rules は emotion vector engineering |\n| [`agentic-search-five-phase-refactor`](https://github.com/Liplus-Project/liplus-language/wiki/agentic-search-five-phase-refactor) | agentic-search 5-phase refactor — skill encapsulation と内部知識の比較基線化 |\n| [`character-instance-output-styles-migration`](https://github.com/Liplus-Project/liplus-language/wiki/character-instance-output-styles-migration) | Character_Instance loading mechanism を rules slot から output-styles slot に移行 (Claude adapter) |\n| [`li-plus-lightening-l1-gate-override`](https://github.com/Liplus-Project/liplus-language/wiki/li-plus-lightening-l1-gate-override) | Li+ lightening 文脈での L1 gate override 判断 |\n| [`subagent-state-machine-label-mechanism`](https://github.com/Liplus-Project/liplus-language/wiki/subagent-state-machine-label-mechanism) | subagent state-machine label 機構導入判断 (in-progress / review-pending / waiting / blocked + 部分 label 権限) |\n| [`lsp-integration-out-of-scope`](https://github.com/Liplus-Project/liplus-language/wiki/lsp-integration-out-of-scope) | LSP 統合は Li+ スコープ外 — 言語ごと常駐サーバ重量と汎用 harness 原則の衝突 |\n| [`character-instance-opt-in-and-surface-scope`](https://github.com/Liplus-Project/liplus-language/wiki/character-inst"
              },
              {
                "source_id": "T62S3",
                "repo": "Liplus-Project/github-rag-mcp",
                "title": "docs/0-requirements.md",
                "url": "https://github.com/Liplus-Project/github-rag-mcp/blob/main/docs/0-requirements.md",
                "source_updated_at": "2026-10-02T13:01:28.567Z",
                "rerank_score": 0.05872976407408714,
                "state": "active",
                "content_truncated": true,
                "excerpt": "docs/0-requirements.md\n\n# github-rag-mcp Requirements Specification\n\nLanguage: English | [Japanese](0-requirements.ja.md)\n\n## Overview\n\n`github-rag-mcp` is an MCP server that gives AI agents retrieval over GitHub project state.\n\nThe system indexes:\n\n- issues\n- pull requests\n- releases\n- repository documentation\n- commit diffs (judgment history, including changes to deleted files)\n\nThe design goal is not transcript memory. The goal is recoverable project state.\n\nThis project treats GitHub as a shared working memory:\n\n- Issues preserve requirements, open decisions, and task state.\n- Pull requests preserve implementation, review, and CI state.\n- Docs preserve stabilized understanding.\n- Releases preserve shipped checkpoints.\n- Commit diffs preserve the judgment history of what changed and why (including deleted files and non-`.md` extensions).\n\nSearch is used to recover the relevant slice of that state when an agent needs to act.\n\nCounterpart:\n\n- [github-webhook-mcp](https://github.com/Liplus-Project/github-webhook-mcp) provides push-based awareness.\n- `github-rag-mcp` provides retrieval over durable state.\n\n## Principles\n\n### State over complete memory\n\nThe project does not aim to store every conversation or every reasoning trace.\n\nInstead it preserves the state required for the next correct action.\n\n### No unnecessary additions\n\nThe memory layer should not add speculative or decorative information that changes the meaning of the original GitHub artifacts.\n\n### No loss of required information\n\nThe memory layer should not remove the constraints, decisions, and current status that another agent or session needs to continue the work safely.\n\n### Human-visible memory\n\nThe source artifacts remain human-readable and reviewable. Retrieval is an index over those artifacts, not a hidden replacement for them.\n\n## Architecture\n\n```text\nGitHub webhooks + GitHub API\n            |\n            v\n     Cloudflare Worker\n     + MCP surface\n     + webhook receiver\n     + cron poller\n     + embedding pipeline\n     + hybrid retrieval (dense + sparse + RRF fusion + cross-encoder rerank)\n            |\n            +--> Vectorize             (dense: BGE-M3 1024d, cosine)\n            +--> D1 FTS5               (sparse: BM25, porter + trigram)\n            +--> Durable Object/SQLite (structured state, watermarks)\n            +--> Workers AI BGE-M3     (embedding generation)\n            +--> Workers AI bge-reranker-base (cross-encoder rerank)\n```\n\n## Components\n\n### 1. MCP Surface\n\nThe worker exposes MCP tools over HTTP.\n\nResponsibilities:\n\n- accept authenticated MCP requests\n- expose semantic and structured retrieval tools\n- return state in a format that downstream agents can consume directly\n\nWorker Zod contracts are the source of truth. The bridge answers `tools/list` from generated static JSON without startup auth/network. `scripts/generate-tool-contracts.mjs` regenerates those artifacts; `scripts/check-schema-drift.mjs` compares all four tools against their actual served nested input/output schemas, bounds, defaults and annotations in CI. This extends the previous name/enum-only guard (#259).\n\n#### Protocol revision: 2026-07-28, single lane\n\nThe Worker serves MCP protocol revision **2026-07-28 only**. There is no\ncompatibility lane for the 2025 era: a request without the revision's\nper-request `_meta` envelope — including a 2025 `initialize` handshake — is\nanswered with the unsupported-protocol-version error naming the one revision\nthe endpoint serves. The SDK offers a stateless fallback for the older era;\nit is deliberately not enabled (gh#224).\n\nThe reason is not that a fallback would be technically wrong, but that an\nunmaintained one becomes dead code. Its removal condition is observable (no\ntraffic reaches the old lane) yet nobody goes and observes it. The breakage is\nabsorbed on a different channel instead: a minor release plus a README notice.\n\nConsequences of statelessness:\n\n- No session. Each request is served by a server instance built for it alone,\n  so nothing is resolved from a session ID and `mcp-session-id` is not issued.\n- User identity comes from the OAuth props of the request being served, read\n  through the handler's per-request auth context rather than from an instance\n  field.\n- The Durable Objects that once served MCP (`RagMcpAgent`, `RagMcpAgentV2`) are\n  out of the serving path. Their classes remain exported as retired stubs\n  because Cloudflare requires every class named in a past migration to exist in\n  the script; removing them needs a `deleted_classes` migration. `IssueStore`,\n  which holds real data, gains independent memory tables in #259.\n\nThe revision is a private contract between this repository's two artifacts. The\nnpx bridge (`mcp-server/`) is the only way to reach the Worker — `server.json`\ndeclares stdio transport alone — so no third-party client negotiates with it,\nand the bridge pins the revision instead of probing for it. The bridge's own\nface toward Claude Desktop stays on SDK v1 / the 2025 era; that side is a\nseparate migration (gh#228).\n\nBecause the Worker is one shared deployment and each bridge is per user, the\nflip is asymmetric: the Worker moves at once, while a bridge follows only when\nits host process restarts. A user pinned to an older bridge version does not\nrecover by restarting. That cohort is explicitly cut off.\n\n### 2. Webhook Receiver\n\nThe webhook receiver ingests GitHub events in near real time.\n\nSupported event families:\n\n- `issues`\n- `pull_request`\n- `release`\n- `push`\n\nResponsibilities:\n\n- verify webhook signatures with `GITHUB_WEBHOOK_SECRET`\n- validate GitHub source IPs\n- route events to the embedding pipeline\n- update both semantic and structured stores\n\n`push` is used to detect changes in all `.md` files across the repository. The same `push` events also drive per-commit diff indexing: each commit produces N vectors (one per file with a textual patch), with embedding input being `commit message + file path + patch`. This surface makes deleted files and non-`.md` extensions searchable as judgment history.\n\n**Doc deletions on the `push` path** tear down the same three surfaces the cron reap does — Vectorize, D1 FTS5, and the structured store — each independently, so one failing surface cannot strand the others (issue #206). Graph edges are again not torn down, for the same reason as the cron reap: a doc vector ID is never a `doc_edges` endpoint. Unlike the cron reap there is no per-run deletion cap: a push payload names its own removals, so the loop is bounded by the event rather than by an accumulated backlog. The `deleted` count in the response body counts docs whose three surfaces all came down, so `removed - deleted` is the partial-teardown count visible in the delivery log; the cron reap's counter instead counts attempts, because there it doubles as the budget counter that gates the ETag hold.\n\n### 3. Cron Poller\n\nThe cron poller is the fallback path.\n\nResponsibilities:\n\n- repair missed webhook deliveries\n- backfill new repositories\n- refresh changed issues, pull requests, releases, docs, GitHub Wiki pages, issue/PR comments, and commit diffs\n- keep the stores converged even after transient failures\n\nThe poller runs hourly in the current deployment, split across four cron triggers so each invocation gets its own Cloudflare Workers subrequest budget. Each upsert fans out to Store DO + Vectorize + D1 FTS + AI embed (up to four internal subrequests), so even the comments + diffs combination overshoots the per-Worker ceiling on busy repositories; the heavy surfaces run one-per-cron, staggered by 15 minutes:\n\n- **`0 * * * *` (light)** — issues, pull requests, releases, docs\n- **`15 * * * *` (comments)** — issue / PR comments only\n- **`30 * * * *` (diffs)** — commit diffs only\n- **`45 * * * *` (wiki)** — GitHub Wiki pages only\n\nDispatch is performed inside `handleScheduled` by inspecting `controller.cron`. Unknown cron expressions fall through to a no-op log to prevent silent regressions when triggers are added lat"
              }
            ]
          }
        ]
      },
      "outputs": {
        "r8": {
          "answers": [
            {
              "case_id": "T31",
              "status": "premise_corrected",
              "answer": "60000 トークンと「batch 件数 × 最長入力」の記述は batch embedding の話であり、bge-reranker-base に適用できる根拠ではありません。2026年8月の #246 では padding による計数を観測からの未確定の推論として示しています。reranker の #91 は入力上限の確認と truncate を要求するだけなので、提供資料から reranker の具体的上限や現在の提供挙動は確認できません。",
              "source_ids": [
                "T31S1",
                "T31S2",
                "T31S3"
              ],
              "quotes": [
                "Workers AI の batch embed が拒否する量は、入力の**合計**ではなく **`batch 件数 × batch 内の最長入力`** である可能性が高い。",
                "**確からしさ**: 4 観測からの推論であり、確定ではない。",
                "reranker 呼び出しの input content 上限を確認・実装 (モデルの context window を超えないよう truncate)"
              ]
            },
            {
              "case_id": "T84",
              "status": "premise_corrected",
              "answer": "合計を縛ればよいという #244 の方針は、後続の #246 が訂正しています。#246 は UTF-8 バイト版でも失敗した観測を示し、batch_size × max_over_inputs(utf8ByteLength(input) + TOKEN_OVERHEAD_PER_INPUT) を上限以下にする境界を求めています。ただし、件数×最長で消費されるという provider の計数モデルは当時の4観測からの未確定の推論です。この履歴だけで現在の実装・デプロイ状態は断定できません。",
              "source_ids": [
                "T84S1",
                "T84S2"
              ],
              "quotes": [
                "1 batch の合計 UTF-8 バイト数 <= 60,000 - (special token 分)",
                "batch_size × max_over_inputs(utf8ByteLength(input) + TOKEN_OVERHEAD_PER_INPUT) <= WORKERS_AI_BATCH_CONTEXT_LIMIT",
                "**確からしさ**: 4 観測からの推論であり、確定ではない。",
                "合計軸の予算(`MAX_EMBEDDING_BATCH_BYTES` を合計に対して適用する形)は退役させる。"
              ]
            },
            {
              "case_id": "T62",
              "status": "insufficient",
              "answer": "提供された抜粋では、github-rag-mcp の wiki グラフが mention を保存するのか、supersedes の意味を分類するのか判定できません。Decision-Structure の資料は Li+ の判断記録における意味グラフと edge 宣言の仕様であり、github-rag-mcp の抽出・保存方式の仕様とは区別が必要です。github-rag-mcp 要件の抜粋には doc_edges への言及はありますが、この分類方式を説明する箇所は確認できず、全資料が途中で切れています。",
              "source_ids": [
                "T62S1",
                "T62S2",
                "T62S3"
              ],
              "quotes": [
                "判断ノード (state 形エントリ) と supersede / depend / conflict edge による意味グラフ",
                "**supersedes** = この判断は別 entry の判断を置き換える。",
                "a doc vector ID is never a `doc_edges` endpoint."
              ]
            }
          ]
        },
        "v3": {
          "answers": [
            {
              "case_id": "T31",
              "status": "premise_corrected",
              "answer": "60000 トークンと「batch 件数 × 最長入力」の話は、提供資料では埋め込み(batch embed)の予算についてです。bge-reranker-base の上限としては確認できません。2026年8月15日の #246 はこの計算を観測からの未確定な推論としています。reranker の2026年4月19日の #91 は入力上限の確認・実装を要求していますが、数値を示していません。これらの履歴だけで、現在の reranker がその方式で60000トークンまで使えるとは判断できません。",
              "source_ids": [
                "T31S1",
                "T31S3"
              ],
              "quotes": [
                "Workers AI の batch embed が拒否する量",
                "**確からしさ**: 4 観測からの推論であり、確定ではない。",
                "reranker 呼び出しの input content 上限を確認・実装 (モデルの context window を超えないよう truncate)"
              ]
            },
            {
              "case_id": "T84",
              "status": "insufficient",
              "answer": "このパケットには資料が提供されていないため、全入力のUTF-8バイト数の合計を縛ればよいか判断できません。",
              "source_ids": [],
              "quotes": []
            },
            {
              "case_id": "T62",
              "status": "insufficient",
              "answer": "このパケットには資料が提供されていないため、wiki グラフが参照の mention を保存するのか、supersedes という意味の関係を分類するのか判断できません。",
              "source_ids": [],
              "quotes": []
            }
          ]
        },
        "m6": {
          "answers": [
            {
              "case_id": "T31",
              "status": "premise_corrected",
              "answer": "60000 トークンと「batch 件数 × 最長入力」の記述は batch embedding の予算についてであり、bge-reranker-base の上限を示していません。2026-08-15 の #246 でも padding による計数は観測からの推論で、確定ではないと明記されています。reranker の #91(2026-04-19)は input content 上限を確認・実装するという要件です。したがって、この資料から bge-reranker-base がその式で 60000 トークンまで使えるとは確認できません。",
              "source_ids": [
                "T31S1",
                "T31S2",
                "T31S3"
              ],
              "quotes": [
                "Workers AI の batch embed が拒否する量は、入力の**合計**ではなく **`batch 件数 × batch 内の最長入力`** である可能性が高い。",
                "**確からしさ**: 4 観測からの推論であり、確定ではない。",
                "`WORKERS_AI_BATCH_CONTEXT_LIMIT = 60000` は天井の記録として維持",
                "reranker 呼び出しの input content 上限を確認・実装 (モデルの context window を超えないよう truncate)"
              ]
            },
            {
              "case_id": "T84",
              "status": "premise_corrected",
              "answer": "合計を縛ればよい、という前提は後続資料で訂正されています。#244(2026-08-14)は UTF-8 バイト数の合計を提案しましたが、#246(2026-08-15)はその版の稼働後も 60678 トークンで失敗した観測を示し、合計軸を退役させ、batch_size × max_over_inputs(utf8ByteLength(input) + TOKEN_OVERHEAD_PER_INPUT) <= WORKERS_AI_BATCH_CONTEXT_LIMIT を求めています。ただし provider が最長入力への padding で計数するという説明は未確定の推論です。この歴史的 issue だけで現在の実装・配備や provider の挙動までは断定できません。",
              "source_ids": [
                "T84S1",
                "T84S2"
              ],
              "quotes": [
                "1 batch の合計 UTF-8 バイト数 <= 60,000 - (special token 分)",
                "合計軸の予算(`MAX_EMBEDDING_BATCH_BYTES` を合計に対して適用する形)は退役させる。",
                "batch_size × max_over_inputs(utf8ByteLength(input) + TOKEN_OVERHEAD_PER_INPUT) <= WORKERS_AI_BATCH_CONTEXT_LIMIT",
                "**確からしさ**: 4 観測からの推論であり、確定ではない。"
              ]
            },
            {
              "case_id": "T62",
              "status": "insufficient",
              "answer": "提示された抜粋だけでは、github-rag-mcp の wiki グラフが mention を保存するのか、supersedes を意味関係として分類するのか判定できません。T62S1 は neuron-graph-rag 内の corpus、T62S2 は liplus-language の Decision Structure 運用仕様で、判断エントリの supersedes / depends on / conflicts with という語彙と前方リンクの書き方を述べています。これは検索サーバの保存・分類方式の証拠にはなりません。github-rag-mcp 自身の T62S3 は doc vector と doc_edges endpoint の関係には触れていますが、提示範囲では wiki edge の種別を確定できず、3 資料とも content_truncated=true です。",
              "source_ids": [
                "T62S1",
                "T62S2",
                "T62S3"
              ],
              "quotes": [
                "**supersedes** = この判断は別 entry の判断を置き換える。",
                "edge は前方リンク(本 entry から相手 entry へのリンク)として書く。",
                "a doc vector ID is never a `doc_edges` endpoint."
              ]
            }
          ]
        }
      },
      "adjudication": {
        "scope": "three development controls, one fresh reader per arm, not holdout",
        "results": {
          "T31": {
            "r8": "premise_corrected",
            "v3": "premise_corrected",
            "m6": "premise_corrected"
          },
          "T84": {
            "r8": "premise_corrected",
            "v3": "insufficient",
            "m6": "premise_corrected"
          },
          "T62": {
            "r8": "insufficient",
            "v3": "insufficient",
            "m6": "insufficient"
          }
        },
        "quotes_verified": true,
        "hashes": {
          "near-arm-r8.json": "00d578e68b25b6e399fa0dcce8120f5d7bf36221cee16d75ba3a4e045340c32f",
          "near-output-r8.json": "b414c403c34d694ea80e92ed219ef7a8ba144b7154f99d71d61e04a9f6cb1c66",
          "near-arm-v3.json": "f8b38ac260543f51a7e1388a68b1afc8f502b8109bddfa514066dcca15d0f849",
          "near-output-v3.json": "e444f15f22e84a259a02ca678a20a7771c5b5bf36d06bad1030d5dc688993826",
          "near-arm-m6.json": "84a0950155f09a5c37a0facc64bc028a190f679859114d762b04d9b0de10b544",
          "near-output-m6.json": "6cbc2366ceed5574698756a24cdaa7944ce31bfdba42df6bae7e6c917fe1a53d"
        },
        "observed_unsupported_claims": {
          "r8": 0,
          "v3": 0,
          "m6": 0
        },
        "observed_explicit_correction_losses": {
          "r8": 0,
          "v3": 1,
          "m6": 0
        }
      }
    }

    — Luna

  10. lipluscodex commented on Oct 12, 2026

    @lipluscodex
    Member

    Codex Luna

    追加の指示を外す開発比較

    同じnear-arm-r8 packetの3問を、新しい読み手(継承モデル・medium・独立context・各問1回)へ渡した。前の共通promptにある対象/時点/条件/truncationの確認・前提訂正・現在配備への歴史的推論禁止の文章を外し、提供資料だけで回答することと共通JSON status形式は維持した。

    T31はstatusがpremise_correctedからinsufficientへ変わったが、本文ではembeddingとrerankerを区別し、60000上限の転用を否定している。意味上の訂正損失なし。T84は前提訂正、T62は根拠不足で、追加注意ありbaselineと判断は同じ。無根拠断定0/3・訂正損失0/3。全quoteをpacketと照合済み。

    1回/armなので指示の因果効果・一般的無効を証明しない。提供資料限定の基本指示、status選択、standing instructionsは残る。今回の明示的確認文を追加する利益は観測しなかったため、ツール説明/結果への新しい定型文は導入しない。既定変更なし。ここまでの開発試験結果は固定packetとともに保存済みで、108問いholdout/反復は残る別の評価作業。この調査ラウンドを終了し、issueはopen backlogで保持する。

    読取結果
    {
      "answers": [
        {
          "case_id": "T31",
          "status": "insufficient",
          "answer": "提供資料だけでは、bge-reranker-base がその式で60000トークンまで使えるとは確認できません。60000と件数×最長入力の議論は batch embedding の予算についてであり、reranker の上限ではありません。reranker の資料は input content 上限を確認・実装するという制約のみで、具体的な上限を示していません。なお、embedding の padding 課金式も資料では4観測からの未確定の推論です。",
          "source_ids": [
            "T31S1",
            "T31S2",
            "T31S3"
          ],
          "quotes": [
            "Workers AI の batch embed が拒否する量は、入力の**合計**ではなく **`batch 件数 × batch 内の最長入力`** である可能性が高い。",
            "`WORKERS_AI_BATCH_CONTEXT_LIMIT = 60000` は天井の記録として維持",
            "reranker 呼び出しの input content 上限を確認・実装 (モデルの context window を超えないよう truncate)",
            "4 観測からの推論であり、確定ではない。"
          ]
        },
        {
          "case_id": "T84",
          "status": "premise_corrected",
          "answer": "いいえ。#244は合計UTF-8バイト数を縛る方針でしたが、その版でも上限超過が続き、後続の#246は縛る量そのものを誤りと診断しています。#246が要求する境界は batch_size × max_over_inputs(utf8ByteLength(input) + TOKEN_OVERHEAD_PER_INPUT) <= WORKERS_AI_BATCH_CONTEXT_LIMIT で、合計軸の予算は退役させます。ただし、最長入力へのpaddingによる課金という説明は4観測からの未確定の推論であり、提供資料から現在の実装や成功実測までは確認できません。",
          "source_ids": [
            "T84S1",
            "T84S2"
          ],
          "quotes": [
            "1 batch の合計 UTF-8 バイト数 <= 60,000 - (special token 分)",
            "batch_size × max_over_inputs(utf8ByteLength(input) + TOKEN_OVERHEAD_PER_INPUT) <= WORKERS_AI_BATCH_CONTEXT_LIMIT",
            "合計軸の予算(`MAX_EMBEDDING_BATCH_BYTES` を合計に対して適用する形)は退役させる。",
            "4 観測からの推論であり、確定ではない。"
          ]
        },
        {
          "case_id": "T62",
          "status": "insufficient",
          "answer": "提供資料では、github-rag-mcp のwikiグラフが参照mentionを保存するのか、supersedes等の意味関係を分類するのかを判定できません。Decision Structureの資料は、wiki執筆側の意味グラフとedge語彙を定義し、edgeを前方リンクとして書くことを示していますが、これはgithub-rag-mcpの関係抽出・保存方式を示す仕様ではありません。github-rag-mcpの要件抜粋にはdoc_edgesへの言及はあるものの、wikiのedge種別や分類方法は含まれていません。",
          "source_ids": [
            "T62S2",
            "T62S3"
          ],
          "quotes": [
            "判断ノード (state 形エントリ) と supersede / depend / conflict edge による意味グラフ",
            "edge は前方リンク(本 entry から相手 entry へのリンク)として書く。",
            "a doc vector ID is never a `doc_edges` endpoint."
          ]
        }
      ]
    }

    — Luna

  11. added
    backlog受け入れ済み、着手時期未定
    and removed
    in-progress着手中、実装または検証が進行中
    on Oct 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

backlog受け入れ済み、着手時期未定enhancement新機能・改善要望ready本文が実装開始できる形まで収束している状態。ただし更新は継続可能

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions