- 起票: 2026-09-22
- 状態: Done(2026-09-22)。rev2(P0 の実測 + 査読 2 系統 18 点 → 採用 12 / 訂正して採用 5 / 反証 1。
採否は Notes 4)→ 承認 → P0 完了 → P1 完了(同日。裁定 2 点は利用者が yes =
_prunedキーを足すことを 認める / 縮んだ効き目で進める。tool_prune_contractへ「配列型」の節を凍結。P1 =prune.rsにJsonScannerと配列型の割り方・組み立て。core 810 全緑・ミューテーション 4 本のうち 1 本で予測を外した。 P2 完了 = 結合 2 本・変異 2 本とも予測どおり。P3 完了 = DETAIL 3 言語 / PRIVACY 日英 / README 3 言語。 P4 = 実機 5 走行で Done)。起票から Done まで同日。 rev1 の D1〜D5 は P0 で前提が覆ったので全面的に書き直した — rev1 の文面は Notes 5 に写しを残す - 起点: Spec 59 の P0 で測った返り値の形(2026-09-22)。対象の呼び出しのうち 4,000 字以上の 5,246,474 字を、実際にツールを叩いて分類したら 30.1% が JSON の配列型だった。 Spec 59 は「JSON は包装型だけ扱う」で着地したので、この 30.1% は素通しのまま残っている。 利用者裁定(2026-09-22)—「B は足す、C は別 Spec に切る」
- 覆す凍結: 無い。Spec 59 の
tool_prune_contractに足す形(既存の凍結は 1 つも動かさない)
- トップレベルがオブジェクトで、その直下に配列を持つ JSON のツール結果から、そのターンの依頼に 関係の無い要素を、モデルへ返す前に落とす。 落とした後もJSON として読めるままで、 配列の要素の型は揃ったままであること(印を要素として混ぜない)
- 残る要素は逐語。 要素の中身を要約も言い換えもしない
- 落としたことと、落としたものへ戻る道を書く(
failures.md#44) - Spec 59 の機構を借りる —
ParagraphScorer/ 閾値 / 設定(jev.json)/omitted/ 計器。 新しく作るのは割り方と組み立てだけ - 形が揃わなければ丸ごと諦める(
outcome=structuredのまま)。部分的に解釈して構文を壊す 経路を作らない(AionUi のtoonと Spec 59 D4b と同じ規律)
やらないこと(範囲外): Spec 59 が扱う範囲(本文と包装型)/ トップレベルが配列の JSON
(実例 0 件。印の置き場が無い)/ 直下より深い配列(elyth の 3 段目。P0 実測 1)/
要素の中身を切り詰めること(要素は落とすか残すかの 2 値)
| 分類 | 字数 | 割合 | 実測した例 |
|---|---|---|---|
| A. JSON でない(Spec 59 の対象) | 1,283K | 24.5% | MCP_DOCKER__fetch / rag |
| B. JSON・包装型(Spec 59 D4b の対象) | 291K | 5.5% | manuale__read |
| C. JSON・配列型(本 Spec の対象) | 1,581K | 30.1% | outcasts__recent_posts / memoria__recall_memory / manuale__search |
| D. 同サーバーの他ツール(高確度で JSON) | 949K | 18.1% | alphaxiv__* / manuale__navigate |
| E. 不明(この端末から叩けない) | 1,142K | 21.8% | elyth__* / browsermcp__* |
通しの効き目(rev1 の見積もり): Spec 59 だけ 6.0% → 本 Spec を足すと 12.1% = 約 2 倍
→ rev2 で訂正(P0 の母数 4,903,900 字で数え直した。査読 #1 矛盾 10):
Spec 59 が割れる(A + B) 1,245K = 25.4% fetch 875 / get_paper_content 75 / manuale__read 291 …
Spec 59 の対象だが割れない(A') 810K = 16.5% answer_pdf_queries 787(XML・空行なし)/ discover_papers 23
本 Spec が効く見込み(C の一部) 1,343K = 27.4% outcasts 989 / manuale__search 204 / memoria の長い文字列 ≈150
本 Spec の対象だが効かない 948K = 19.3% elyth 713(3 段目・50 字抜粋)/ navigate 85 / memoria の規律文 ≈150
対象外・未分類 558K = 11.4%
本 Spec が足す母数は Spec 59 と同規模(1.34M 対 1.25M)で、「2 倍」ではなく「同じくらいをもう 1 つ」。 しかも削減率は依頼の狭さで 12% ↔ 68% に割れる(P0 実測 2)ので、門を超えるのは狭い依頼のときだけ。
閉じた条件 3 つをすべて満たす本文だけを対象にする(Spec 59 D4b と同じ流儀 — 外れたら
outcome=structured のまま素通し。部分的に解釈しない):
- トップレベルがオブジェクト(配列なら対象外 — 印の置き場が無い。実例 0 件)
- 直下に配列が 1 つ以上あり、そのうち JSON 表現が 1,000 字以上の配列を対象にする。
門は要素数ではなく字数(P0 実測 2-3: 3 件で 12K 字を占める配列が実例)。1,000 字未満の配列
(
next_hints/capabilities/counts_by_type)は触らない - 直下より深い配列は探さない(
elythのdata.timeline.items。届いても要素が 50 字の抜粋で Jev に判定材料が無い = P0 実測 1・2-2)
複数の配列が対象になりうる(memoria__recall_memory は 7 つ、manuale は 2 つ)。
対象の配列それぞれが独立に採点・判定される(D6)。対象の配列が 0 なら structured。
要素の JSON 表現(serde_json の compact 表現ではなく、元テキストの上でその要素が占める
範囲の逐語)を Spec 59 の「1 段落」として ParagraphScorer へ渡す。
- 採るのは JSON 表現。
構造が見えるぶん判断材料が増える→ P0 実測 2-5 で否定(Jev はauthored_modeのような構造の条件を読み分けない。見ているのは本文の語)。採る理由は 「落とすものと採点に送ったものが同一物」の 1 つだけ(文字列連結との差は小さい = 2-4) - 6,000 字超の要素は採点せず残す(Spec 59 D6 の凍結をそのまま借りる)。
searchの base64 画像 (20K 字超)はここで自然に外れる。6,000 字の崖は Spec 59 の凍結で、本 Spec では動かさない - 全対象配列の要素を 1 本の候補列に平坦化して
prune::batchへ渡す(束ね方の唯一の実装。 Spec 59 D4 の 6)。戻ったスコアは(配列の鍵, 要素の index)の対応表で戻す — Spec 59 のPreparedが段落の index でやっていることと同じで、鍵が 1 つ増えるだけ
トップレベルに _pruned を 1 キー足す。 配列の中に印の要素は入れない(A — 要素の型が揃わず
Post[] として読む側が壊れる = Goal 1 / Goal 5 違反)。JSON の外にも置かない(C — 本文が JSON で
なくなる = Goal 1 違反)。
{"posts":[…残った要素…],
"_pruned":{
"note":"関連度で要素を省略しています。omitted(id, from, to) で逐語が読めます",
"arrays":{
"posts":{"id":"P2","total":12,"dropped":[0,3,11]}
}}}- 配列ごとに
idを 1 つ振る(P{n}の通し番号。Spec 59 のself.pruned.len() + 1をそのまま使う)。omitted { id, from, to }の引数は変えない —idが配列を、from/toがその配列の要素の index を指す(査読 #2 矛盾 1 の解) noteはモデルへの案内(Spec 59 の印の文面と同じ役割。【…】の代わりに JSON の値で運ぶ。ja / en は→ P1 で訂正: Spec 59 の印も日本語固定でLanguageで選ぶprepare/applyはLanguageを受け取らない。2 つの印を同じ規律にそろえ、本 Spec だけ二言語にしない)- 元の JSON に
_prunedが既にあれば丸ごと諦める(structured)。上書きも改名もしない(Goal 5) - これは「元の JSON に無いキーを足す」変更で、Spec 59 の「圧縮した文字列以外は 1 バイトも
変わらない」より一段ゆるい。 要素を消す以上、構造は必ず変わる(カンマが動く)ので、
「変わるのは対象の配列の中身と
_prunedの 1 キーだけ」を凍結の文面にする(未決 1 = 利用者裁定)
元テキストの上で、落とす要素の範囲(先行または後続のカンマ 1 つを含む)を消し、末尾の } の
直前に ,"_pruned":{…} を挿入する。 他は 1 バイトも触らない。
- 再シリアライズは除外 —
serde_jsonはキー順・空白・数値表現(1.0と1)を変える(Goal 2 違反。 実物は整形あり / なしが混在するので、整形も必ず変わる) - 要素の範囲は自前のスキャナで取る(文字列リテラルとエスケープ・括弧の深さだけを追う)。 Spec 59 D4b が「最長の文字列リテラルの位置」を探す走査を既に持っている — 着手時に共有できる 部分を数える(P1 の 1 本目)
- カンマの規則: 落とす要素が末尾なら先行のカンマを、それ以外なら後続のカンマを消す。 空白・改行は触らない(整形が崩れて見えても JSON として正しい — 崩れ方は fixture で焼く)
- バイト golden: 素の JSON(
outcasts)と整形 JSON(memoria/manuale)の 2 fixture で、 「対象の配列の中身と_pruned以外は 1 バイトも変わらない」を留める(Spec 59 のeverything_outside_the_compressed_string_is_byte_identicalと同じ形)
Spec 59 の omitted { id, from, to } と PrunedRaw { id, paragraphs, dropped } を無改変で共有する。
PrunedRaw.paragraphs に要素の逐語を入れれば、omitted は段落と同じ経路で返す —
PrunedRaw は中身が段落か要素かを知らない(kind 欄は要らない。査読 #1 矛盾 9 の訂正)。
モデルが読む区別は _pruned.note と arrays の鍵が担う。
判定は配列ごと(Spec 59 の apply を配列 1 つに 1 回):
- ある配列で採点した要素がすべて閾値未満なら、その配列は触らない(Spec 59 の
all_droppedと 同じ理由 — 依頼と噛み合っていないか採点の失敗。空配列[]は作らない) - ある配列で1 つも落ちなければ、その配列は触らない
- 対象の配列がすべて「触らない」なら、本文全体を素通し。
outcomeは全配列が all_dropped ならall_dropped、それ以外はnothing_dropped - 1 つ以上の配列で落ちたら組み立て、正味の門(D7)へ
| 門 | 何を見るか | どこで |
|---|---|---|
| 対象の門(D1) | 配列の JSON 表現が 1,000 字以上か | 採点の前。外れた配列は Jev へ送らない |
| 正味の門(Spec 59 D6b) | 組み立てた本文全体の削減率が 25% 以上か | 組み立ての後。MIN_REDUCTION をそのまま借りる |
正味の門は本文全体で測る(配列ごとではない)。固定欄が大きくて届かなければ below_floor で
素通しになるが、それが正しい — モデルに届くのは本文全体で、そこが 25% 減らないなら印を足す
価値が無い(Spec 59 rev4 の論拠そのまま。査読 #2 不整合 5 は「明記されていない」の指摘として採り、
配列ごとに測る案は採らない)。
- D と E を分類した(2026-09-22。下の「P0 実測」)—
alphaxiv__answer_pdf_queries(787K)は XML で JSON ではない。elyth(713K)は配列が 3 段目に居て本文が 50 字の抜粋 = 届かず、届いても 判定できない(利用者が GUI のツール行で確認)。どちらも本 Spec の効き目に乗らない - 実測の 3 例で D1 の条件が成立するか — 成立しない。 複数配列は
memoriaだけでなくmanualeの 2 本(navigate/search)にもあり、rev1 の D1 では配列型の 38%(595K)が落ちる - 配列型の削減率を実測した(3 本・4 依頼文・JSON 表現と文字列連結の 2 通り)
-
data_contract.yamlのtool_prune_contractへ「配列型」の節を凍結(2026-09-22。退けた形に 4 つ足し、shape=json_arraysを計器へ)
- 対象の門(D1): トップレベルがオブジェクト / 直下の配列 / 1,000 字 /
_pruned衝突なら諦める - 自前スキャナで直下の配列と要素の元テキスト上の範囲を取る — D4b と共有できる部分は無かった
(D4b はスキャナを持たず
match_indices。P1 実装記録)。JsonScannerを新設 - 平坦化した候補列 →
prune::batch→ 対応表で配列へ戻す(D2)—Prepared.layoutの 3 値化でcandidates/batches/spreadは無改変 - 配列ごとの
apply(D6)→ 組み立て(D4)→ 正味の門(D7) -
PrunedRawを配列ごとに積む(D5)—Pruned.entriesをapplyが作り、turn.rsは積むだけ - 素 / 整形の両方でカンマの 3 位置(先頭 / 中 / 末尾)+ 配列の外と印以外はバイト同一 + 全滅の配列は
触らない +
_pruned衝突 + 1,000 字未満は対象外 + 文字列の中の括弧 + 包装型が先 + 6,000 字超の要素 + 正味の門は全体。14 本。変異 4 本で赤を確かめた(1 本は予測を外した)
-
prune::prepareの入口で D4b(包装型)と本 Spec(配列型)を1 箇所で分岐(Notes 1)— P1 で済んだ - 計器
tool prune:にshape=json_arrays arrays=<対象の配列数> pruned=<落とした配列数>— P1 で済んだ - 結合 2 本(
tests/tool_prune_arrays.rs。偽の採点器で経路を丸ごと通す): 配列型が圧縮されても本文が JSON のまま・omittedが次の周で要素を逐語で返す / 落とした配列ごとに別の id・omittedの index は その配列の中で数える(P2, 1が y の要素 1 を返し、x の要素 1 も平坦化の 1 番目も返らない)。 変異 2 本(turn.rsが entries の 1 件目しか積まない / entry のparagraphsを平坦化した全要素にする)は どちらも予測どおり 2 本目だけ赤
- DETAIL 日英に「配列型は要素単位で落とす」の段落(包装型の段落の直後。中国語版は抄訳に 1 項)/
PRIVACY 日英の 4-4 に**素通しの条件へ「配列型でもない」**と、**送るもの = 段落の代わりに要素の JSON
表現(キー名を含む)**の 1 文 / README 3 言語は既存の行に「(JSON なら配列の要素)」を挟んだだけ
(169 / 169 / 165 行のまま)。隣の欠けを 1 件回収 — PRIVACY 日英の「送る本文には
ragが読んだ 宣言フォルダの中身が含まれる」は Spec 59 rev4 でragを外した後も残っていた(rev4 の P3 の追従漏れ) - 実機:
outcasts__read_threadを狭い依頼でoutcome=ok(話題で 62%。「誰が」では 6% = Jev が答えられる 問いの形は話題)/memoria__recall_memoryで複数配列の_pruned(pruned=3)/ 広い依頼でbelow_floor(6.3% と 23.5%)。記録は「P4 実機記録」
core 810 / 結合 47 バイナリ 全緑(+14)・clippy 0。新しい依存は 0。次に触る人が要る判断だけを置く。
- Spec 59 D4b と共有できる走査は無かった。 D4b は「
serde_jsonで読み、最長の文字列を 再シリアライズしてmatch_indicesで位置を探す」形で、スキャナを持っていない。要素は整形 (改行・インデント)されていると再シリアライズと一致しないので、配列型はJsonScannerを新設した(文字列リテラルとエスケープ・括弧の深さだけを追う約 100 行。serde_jsonが 読めた本文にだけ掛けるので構文の誤りは想定せず、形が合わなければNone→structured) - 分岐は
prepareの 1 箇所(Notes 1)。順は 包装型 → 配列型 →structured。包装型が先なのは、 巨大な文字列 1 つを持つ本文は配列があってもそちらが本体だから(arrays_yield_to_the_wrapper_shape) Preparedのwrapper: Option<WrapperSlot>をlayout: Layoutの 3 値へ(Text / Wrapper / Arrays)。配列型は要素 1 つが段落 1 つで、空行で割らず短い要素も寄せない(境界は JSON が 決めている)。candidates/batches/spreadは無改変で乗ったapplyのid: &strをfirst_seq: usizeへ変えた。 配列型は落とした配列ごとに id を 1 つ 使うので、番号はapplyが振る。帰結としてPrunedがentries: Vec<PrunedEntry>を持ち、 呼び出し側(turn.rs)は落とした index を数え直さずにそれを積むだけになった — rev4 まではturn.rsがscores < thresholdでdroppedを再計算しており、規律が 2 箇所にあった。 Spec 59 の段落型・包装型は 1 件の entry で、omittedもPrunedRawも無改変- カンマの規則は「隙間」で書いた(D4 の精緻化)。
[と最初の要素の間を g0、要素 i-1 と i の 間(カンマ入り)を g_i、最後の要素と]の間を g_n とし、出力は[+ g0 + 残す要素を出現順に (最初に残す要素の前には何も置かず、2 つ目以降は自分の前の g_i を置く)+ g_n +]。 どの落とし方でも余分なカンマが出ず、1 つも落とさなければ入力と同一バイト。契約の 「先行または後続のカンマ 1 つ」はこの規則の帰結で、「空白・改行は触らない」は落とした要素に 付随する隙間は消えると読む(整形は崩れて見えるが JSON として正しい) below_floorのratioは実測値のまま返す — 一度net_ratioをOptionにして門の外で 0.0 を埋めかけ、a_small_gain_is_not_worth_the_markerが赤で止めた(#72 の規律を自分で破りかけた)- Spec 59 のテスト 1 本の前提が Spec 60 で変わった —
a_json_without_a_direct_string_value_is_skippedは「配列型は素通し」を{"posts":["…"]}で確かめていたが、それは今や配列型の対象。fixture を 入れ子だけの JSON へ差し替え、配列型の側はarrays_*の 14 本が担う - 印の案内文(
_pruned.note)は Spec 59 の印と同じく日本語だけ。 D3 に「ja / en はLanguageで 選ぶ」と書いたが、prepare/applyはLanguageを受け取らず、Spec 59 のrenderも日本語固定 だった。2 つの印を同じ言語規律にそろえるのが正しく、本 Spec だけ二言語にしない(Spec 35 の 追従漏れ候補として別件。rev2 の D3 の文面は訂正) - 計器:
shape=json_arrays arrays=<対象の配列数>はPrepared::shape_fields、pruned=<落とした 配列数>はPruned::extra_fields。前者は採点の前から分かり、後者は組み立ての後にしか無いので 置き場が分かれている - 作業の罠 #130 の 3 例目: bash のヒアドキュメント → Python の文字列 → Rust ソースの 2 層を
通した
\nが実改行になり、テストがコンパイルエラーで止まった(赤くなる側の形。緑のまま汚れる 形ではなかった)。行番号で当ててchr(92)で戻した
ミューテーション 4 本(予測を先に書いてから回した):
| 変異 | 予測 | 実測 |
|---|---|---|
MR1 _pruned の衝突検査を外す |
1 本 | 1 本(予測どおり) |
MR2 全滅の配列を触る([] を作る) |
2 本 | 2 本(予測どおり) |
| MR3 カンマ規則(最初に残す要素の前に隙間を置かない)を外す | 3 本 | 3 本(予測どおり) |
| MR4 対象の門を字数から要素数 5 件へ戻す | 1 本 | 7 本(外した) |
MR4 で外した理由: 対象の門は arrays_of の入口に居るので、要素数へ戻すと 3〜4 要素の fixture が
全部 structured へ倒れ、門のテスト以外の 6 本が unwrap で落ちた。Spec 59 rev4 の MR2(不等号の
反転が 7 本を赤にした)と同じ形 — 門は 1 箇所に見えて、その先の全経路の入口に居る。予測は
「門を直接見るテスト」だけを数えていた。
依頼: 「outcasts__read_thread で b2d73586-… のスレッドから、Outcasts 管理人の書いた投稿をだけ確認してください」
(進行役 agent_8 = gpt-5.6-terra)。
23:33:51 tool prune: agent=agent_8 name=outcasts__read_thread outcome=below_floor
shape=json_arrays arrays=1 raw_chars=18448 paragraphs=20 dropped=1
ratio=0.063 calls=2 jev_tokens=16990 ms=1353
- 機構は合格。 配列型の経路を通り(
shape=json_arrays arrays=1)、postsの 20 要素が段落になり、束ねは 16 + 4 の 2 呼び出し。門が 6.3% で止め、本文は 18,448 字のまま渡った(次の周のcache_write=10839) - 効き目は不合格。 スレッドの 20 投稿のうち管理人(
authored_mode: master)が書いたのは 12 で、 理想の判定なら 8 本が落ち、しかもその 8 本が字数の大半(境界測量士の 3 本だけで 6,000 字超)。 実際に落ちたのは 1 本。 落ちるべき 8 本のほぼ全部が>>11 管理人さんと管理人を名指しして返信し、 管理人の論点を引いて議論しているので、「管理人の書いた投稿」に対して Jev は「管理人について書かれた 投稿」も関係ありと判定した - 一般化: 「誰が書いたか」はメタデータの問いで、本文の語で判定する Jev には答えられない。 P0 実測 2-5
(
authored_modeを読まない)が、実機では「宛名に管理人が居るだけで残る」という形で出た。P0 の 68% は、 あのスレッドが相互参照の少ない形だった偶然。read_threadで効くのは「話題」で絞る依頼だけで、 それも 1 つの話題で回っているスレッドでは大半が残る(P0 の 12% 側)
依頼: 「さっきのスレッドで 8bit CPU や Lean の検証企画について書かれた投稿だけ確認して」(同じ agent_8)。
23:38:48 tool prune: name=outcasts__read_thread outcome=ok shape=json_arrays arrays=1 pruned=1
raw_chars=18448 kept_chars=6959 paragraphs=20 dropped=16 ratio=0.623 calls=2 jev_tokens=16918 ms=2341
- 16 / 20 が落ち、62.3%。残った 4 本の中に該当の #16〜18 が居て、ルナの答えは #16〜#18 を正確に挙げた (利用者の画面で確認)— 走行前に私が「関係するのは 3 本」と書いた集合そのもの
- 検収 1(前方一致): round 2
prompt=17777→ round 3cached=17774、3 トークン差(Spec 59 から通算 5 例目) - 収支: 1 回目(全文)の round 3
cache_write=10839に対し 4,297 = 6,542 トークン減 ≈ $0.016。Jev 16,918 トークン ≈ $0.0007 → 約 23 倍の黒字。omittedは呼ばれていない - 同じ 20 要素で、依頼が「誰が」なら 1 本、「何について」なら 16 本。 Jev が答えられる問いの形は
「話題」で、「属性」ではない — これが
read_threadの効き目の境界
| 時刻 | 個体 | 依頼 | outcome | arrays | 要素 | dropped | ratio | Jev |
|---|---|---|---|---|---|---|---|---|
| 23:37:04 | イクス(grok-4.7) | 「過去を思い出して」(36 字) | nothing_dropped |
2 | 10 | 0 | - | 4,849 / 5.8 秒 |
| 23:44:28 | ザリ(muse-spark) | 66 字 | ok・pruned=3 |
3 | 29 | 22 | 0.611 | 13,471 / 1.5 秒 |
| 23:47:47 | イクス | 41 字 | below_floor |
2 | 10 | 4 | 0.235 | 4,839 / 3.2 秒 |
- 複数配列で複数の id が実機で出た(ザリ:
arrays=3 pruned=3=P1/P2/P3。14,237 → 5,533 字)。 結合テストeach_pruned_array_has_its_own_idが留めていた配線の実物 - イクスの 1 回目は依頼が広く(「過去」)、記憶 10 件のどれも材料なので
nothing_droppedが正しい判定。 代償は Jev 4,849 トークンと 5.8 秒 — Jev 1 呼び出しとして今日いちばん遅い(他は 0.2〜2.3 秒) - イクスの 2 回目が今日いちばん惜しい観測 — 4 / 10 が落ちて正味 23.5%、門(25%)に 1.5 ポイント 届かず全文が渡った。門の値を動かす根拠にはしない(1 点。#47 の規律)。Spec 59 の実機では 0.000 / 0.069 / 0.063 と門から遠い側ばかりだったので、門の近くに実在する入力があることだけを記録する
21:46:29 elyth__get_information outcome=structured raw_chars=6128 calls=0 — 入れ子の配列を探さない(D1 の 3)が
実機で効き、1 バイトも外へ出ていない。
-
outcasts__read_threadを狭い依頼でoutcome=okとomitted— ok は 62% で観測。omittedはどの走行でも 呼ばれなかった(= 落とした要素は要らなかった。結合 2 本が経路を留めている) -
memoria__recall_memoryで複数配列の_pruned— ザリの走行でpruned=3 - 広い依頼で
below_floor— 「誰が」の 6.3% と、イクスの 23.5%
この 5 走行で Done(2026-09-22 利用者裁定)。
母数は fuseforks.log 2026-08-09〜09-22 の MCP 由来・4,000 字以上の出力 4,903,900 字
(Spec 59 P0 の 5.25M とは期間と rag の有無で差がある)。
| ツール | 字数 | 形(実物) | 分類 |
|---|---|---|---|
MCP_DOCKER__fetch |
875K | Markdown(Spec 59 P0) | A |
alphaxiv__answer_pdf_queries |
787K | XML <paper id><page num=N>…</page>…</paper>。PDF 抽出の行で空行が無い |
A' = JSON でないが D4 で割れない |
outcasts__recent_posts |
485K | {"posts":[…]} 配列 1・素の JSON |
C |
outcasts__read_thread |
396K | {"board_slug","id","posts":[…],"title"} 配列 1・素の JSON・要素は投稿 |
C |
memoria__recall_memory |
306K | 配列 7 つ(schema_entries / semantic_matches / … )・要素は文字列とオブジェクトが混在・整形 |
C'(複数配列) |
manuale__read |
291K | 包装型(Spec 59 D4b) | B |
manuale__search |
204K | {"query",…,"matches":[…],"next_hints":[…]} 配列 2 つ・整形。context に base64 画像(20K 字超)が入ることがある |
C' |
outcasts__list_threads |
108K | {"threads":[…]} 配列 1 |
C |
manuale__navigate |
85K | {"entries":[…],"next_hints":[…]} 配列 2 つ・整形 |
C' |
memoria__list_memories |
126K(1 回) | 先頭にテキスト行 Total memories: N + JSON 配列。要素の 9 割が embedding(384 次元) |
対象外(JSON でない) |
alphaxiv__discover_papers |
23K | Markdown の番号付きリスト・空行なし | A |
elyth__get_information(get_notifications / get_my_posts も同じサーバー) |
713K | {"data":{…}} の 1 キー包装。配列は 3 段目(data.timeline.items / data.trending.items など)に 5 件ずつ、1 要素 ≈ 350 字で本文は truncated: true の 50 字抜粋。字数の大半は UUID・時刻・author の入れ子(利用者が GUI のツール行で確認・2026-09-22) |
C'' = 入れ子の配列・短い要素 |
browsermcp__* / admin-procedures__* |
157K | 未分類 | E |
分かったこと 3 つ:
- D の最大は配列型ではなかった。 787K は XML で、Spec 60 の効き目は rev1 の見積もり
(+C で約 2 倍)から伸びない。逆にこの 787K は Spec 59 の対象なのに空行が無いので割れない —
ragと同じ形。<page>境界で割る腕を D4 に足せば効く余地がある(Spec 59 の追補の話で、本 Spec の 範囲外) - 複数配列が主流。 C の 1,584K のうち C' が 595K(38%)。rev1 の D1「配列がちょうど 1 つ」は
memoriaのための例外ではなく、設計の前提を外していた - 配列型の中でも要素の型が 3 種ある — 投稿(長い散文のオブジェクト)/ 規律文(文字列)/ ディレクトリ項目(短い構造)。下の採点で判定の質が型ごとに違った
- E の大半(
elyth713K = MCP 出力の 15%)は配列型だが本 Spec の効き目に乗らない。 配列が 3 段目に居るので D1 のどの案でも届かず、届いても本文が 50 字の抜粋で Jev に判定材料が無い (下の採点の観測 2 と同じ形)。字数の出どころが本文ではなく構造(id / 時刻 / 入れ子)なので、 効くとすれば要素を落とす機構ではなく構造を畳む機構(toonの系譜)だが、authorが入れ子なので あちらの「フラットな同型配列」の条件も満たさない。本 Spec では対象外として閉じる
叩いた実物を scratchpad に置き、Spec 59 と同じ問い(instructions / criteria は jev.rs の逐語)で
要素ごとに Noul 1 問。閾値 0.2。JSON 表現(要素をそのまま)と文字列連結(要素の中の文字列を
改行で連ねたもの)の 2 通りで採点した(未決 2 の対測)。
| 材料 | 依頼文 | 要素 | 落ちた | 削減率 | Jev |
|---|---|---|---|---|---|
read_thread(12 投稿・12,290 字) |
「管理者(人間・authored_mode が master)が何を書いたかだけ」 |
12 | 8 | 67.9% | 11,955 |
| 同 | 「拒否権や権限ゲートの設計についての提案をまとめて」 | 12 | 2 | 12.1% | 11,946 |
recall_memory(17,441 字) |
「Spec 60 について過去に決めたことを思い出して」 | 20 + 5 | 7〜12 + 2 | 11.1〜17.8% | 9,897 |
navigate(1,150 字 = 実機では 4,000 字未満で対象外) |
「Fuseforks の仕様書やアーキテクチャの文書を探して」 | 12 + 5 | 9〜10 + 4 | 62〜68% | 3,447 |
読めたこと 5 つ:
- 依頼文で 12% ↔ 68% に割れる(Spec 59 P0 と同じ性質)。同じ 12 投稿でも「1 人の投稿だけ」なら
8 本落ち、「設計の提案を全部」なら 2 本しか落ちない。門(25%)は配列型でも要る — 後者は
below_floorで止まるのが正しい - 要素の型で判定の質が違う。 投稿(400〜1,500 字の散文)は両端がよく分かれる
(0.07〜0.10 対 0.93)。規律文(Mandate)は 0.2〜0.45 の中間帯に溜まる — 「Spec 60 について」に
対して規律が「関係ある」と判定されがち(Jev が判断型に弱い側)。ディレクトリ項目(
{"type":"dir", "path":"spec","name":"spec"}= 40 字)は全部 0.05〜0.23 で、依頼文が名指ししたspec/architectureも 0.20 / 0.21 — 閾値ぎりぎりで残った。短い要素は判定材料が無く、Jev は決められない - 「要素 5 件以上」の門は逆効果の実例がある。
recall_memoryのsemantic_matchesは 3 件だが 1 件 4,000〜6,000 字で、17K 字のうち 12K 字を占める。うち 2 件(Spec 35 / 38 の索引)は依頼と 無関係で、落とせれば削減率は 11% → 60% 超に跳ねる。門は要素数ではなく配列の字数で切る - JSON 表現と文字列連結の差は小さく、文字列連結がやや落とす側。
read_threadは落ちる本数が 一致(スコアの差 0.01〜0.2)、recall_memoryは 7 対 12。採るなら JSON 表現 — 差し替え(D4)で 落とすのは要素の JSON 表現そのものなので、採点に送ったものと落とすものが同一物になる - Jev は構造の条件を読み分けなかった。 依頼文に
authored_modeが master と書いたのに、author_nameが「Outcasts@管理者」のサーヴァント投稿 2 本(post 7 / 11)が 0.61 / 0.62 で残った。 配列型の売りは構造があることだが、Jev が見ているのは本文の語。構造の条件で落とす期待は持たない
read_thread の依頼 1 では 8,346 字(日本語・約 8,000 トークン)が落ち、Jev は 11,955 トークン。
gpt-5.6-terra の書き込み単価で節約 ≈ $0.020 対 Jev ≈ $0.0005 = 約 40 倍の黒字。
依頼 2 では 1,486 字で門に届かず、Jev 11,946 トークン($0.0005)が捨て金。
Spec 59 と同じ結論 — 効くかどうかは依頼文と要素の形が決め、門が赤字を止める。
| 未決 | 測定が指した向き |
|---|---|
| 1. 複数配列 | 直下の配列すべてを対象にし、門は要素数ではなく配列の JSON 表現が 1,000 字以上。next_hints のような小さい配列は自然に外れる。トップレベルが配列(包装なし)の実例は 0 件なので、その形は対象外として閉じる(印の置き場 B が使えない形を作らない) |
| 2. 表現 | JSON 表現(差は小さく、落とすものと同一物) |
| 3. 印の置き場 | B(トップレベルに _pruned 1 キー) — 未決 1 でトップレベルが必ずオブジェクトになるので置き場が定まる。複数配列を 1 つのキーで記述できる({"_pruned":{"id":"P2","arrays":{"schema_entries":{"dropped":[…]},…}}}) |
| 4. 差し替え | 位置ベース。実物は整形あり(memoria / manuale)と素(outcasts)が混在し、再シリアライズは整形を必ず変える = 「圧縮した文字列以外は 1 バイトも変わらない」を破る。着手時に Spec 59 D4b の文字列リテラルの位置探索が再利用できるか数える |
5. omitted |
PrunedRaw に種別を持たせ、印の文面で「要素」と書く。from / to は要素の index(段落と同じ意味の別名) |
効き目の見積もりの訂正: rev1 は「+C で約 2 倍」と書いたが、C 1,584K のうち実際に効く形は
outcasts の 989K(長い投稿・配列 1 つ)と memoria の semantic_matches(長い文字列)まで。
manuale__navigate は要素が短く、elyth は届かない。伸びるのは MCP 出力の 20〜25% ぶんで、
かつ依頼が狭いときだけ(P0 の依頼 1 と 2 の差)。
測っていないこと: browsermcp__* / admin-procedures__* の 157K(3%)の形 / 実機の manuale__navigate(21K 字・深い階層)で要素が
短いまま 4,000 字を超えたときの判定 / search の base64 画像(6,000 字超の要素として採点対象外に
なるはずだが、実物で確かめていない)。
-
Spec 59 との境界: あちらは「本文(と、本文を包んだ JSON)」、こちらは「構造そのものが データである JSON」。判定は 1 箇所で分岐する(
prune.rsの入口)ので、2 つの Spec が 同じ関数を取り合わない形にすること -
RepeatGuard は圧縮前(Spec 59 D2 と同じ)。配列型でも変わらない
-
効き目の上限は D と E の分類次第で 2 倍動く→ P0 で決着。D の最大は XML、E の大半は 3 段目の配列で、どちらも乗らない。本 Spec が足す母数は Spec 59 と同規模(「実測」の節) -
査読 2 系統の採否(rev2・2026-09-22):
# 指摘 採否 反映 1-1 Goal 1 と D3 案 C が両立しない 採用 C を除外(D3) 1-2 Goal 2 と再シリアライズが両立しない 採用 位置ベース一択(D4) 1-3 Goal 5 と D3 案 A(型が揃わない) 採用 A を除外・Goal 1 に「型は揃ったまま」を足した 1-4 D1 が対象の 38% を自ら落とす 採用 D1 を書き直し 1-5 要素 5 件の門が字数に比例しない 採用 1,000 字の門へ(D1) 1-6 トップレベル配列と案 B が衝突 採用 トップレベル配列を範囲外へ 1-7 案 B は「無いキーを足す」= 凍結より一段ゆるい。 _pruned衝突が未定義採用 + 裁定へ 衝突は諦める(D3)。キーを足すこと自体は未決 1 1-8 D2 の「構造が見える」利点は実測で否定済み 採用 理由を「同一物」だけに(D2) 1-9 PrunedRawにkindが要る訂正して採用 PrunedRawは中身が段落か要素かを知らない(paragraphs: Vec<String>に逐語を入れるだけ)。区別は_pruned.noteと配列ごとのidが担う(D5)。欄は足さない1-10 母数のすり替え 採用 P0 の母数で再計算(「実測」の節) 2-1 複数配列で omitted { id, from, to }が配列を指せない採用 配列ごとに P{n}を振る(D3・D5)。omittedは無改変2-2 トップレベル配列 + B の構文的破綻。用語がずれている 採用 タイトル・Goal 1・範囲外を書き直し 2-3 位置ベース + キー挿入は整形で壊れる「リスクが極めて高い」 訂正して採用 挿入点は末尾 }の直前で、JSON は空白を無視するので構文は壊れない。壊れうるのはカンマだけなので規則を D4 に明記し、3 位置の fixture で留める。「極めて高い」は退け、_pruned衝突の未定義は採った2-4 全部落ちた配列の振る舞いが未定義 採用 D6 を新設(触らない・ []を作らない)2-5 2 つの門が混同されている / 正味は配列ごとか全体か 訂正して採用 D7 で分けた。正味は全体(配列ごと案は採らない — モデルに届くのは全体) 2-6 6,000 字の崖と base64 反証(半分) 崖は Spec 59 D6 の凍結で本 Spec は動かさない。20K の base64 は崖で自然に外れる(送らない)。6K 未満の base64 は未観測 — 機構は足さない(#47) 2-7 複数配列の束ね方が未定義 訂正して採用 平坦化して prune::batchの 1 実装へ(D2)。「マッピングが複雑化」はPreparedに鍵が 1 つ増えるだけ2-8 D1〜D5 と P0 と未決の乖離 採用 Design を全面書き直し・rev1 は Notes 5 へ -
rev1 の Design の写し(P0 で前提が覆った側。何を覆したかが読めるように残す):
Spec 59 D4b と同じく閉じた条件にする。案:
- トップレベルが配列、またはトップレベルのオブジェクトの直下に配列がちょうど 1 つ
- その配列の要素が 5 件以上
- 配列の JSON 表現が本文全体の 60% 以上
- 入れ子の中は探さない
実測の 3 例はこの形に収まる —
{"posts":[…]}/{"query":…,"matches":[…]}/{"schema_entries":[…],"semantic_matches":[…],…}。ただし 3 例目(memoria__recall_memory)は 直下の配列が複数あるので、上の条件では落ちる(未決 1)。1 要素 = Spec 59 の「1 段落」として
ParagraphScorerへ渡す。渡すのは要素の JSON 表現か、 要素の中の文字列を連ねたものか(未決 2)。前者は構造が見えるぶん Jev の判断材料が増えるが、 キー名が毎回同じなので雑音にもなる。6,000 字を超える要素は採点せず残す(Spec 59 D4 と同じ)。
JSON の構文を壊さずに印を入れる方法が 3 つあり、どれも代償がある(未決 3):
案 形 代償 A. 配列の中に印の要素 [{…}, {"_omitted": 7}, {…}]要素の型が揃わなくなる。読む側がパースしていれば壊れる B. トップレベルにキーを足す {"posts":[…], "_pruned":{"dropped":7,"id":"P2"}}元の JSON に無いキーが生える。Goal 2 の逐語は要素についてだが、構造は変わる C. JSON の外に印を置く 【… 7 件を省略 …】\n{"posts":[…]}本文全体が JSON でなくなる。Goal 1 と正面から衝突 私の推し は B — 読む側がパースしても壊れず(未知のキーは無視される)、印の置き場が 1 つに定まる。 ただし「元の JSON に無いキーを足さない」を凍結する選択肢もありうる。
Spec 59 D4b は「元テキストの上で文字列リテラルだけを差し替える」形で、再シリアライズを避けた。 配列から要素を消す場合は同じ手が使えない(消すとカンマの位置が変わる)。案は 2 つ(未決 4):
- 位置ベース — 要素の範囲を元テキストで特定し、その範囲とカンマを消す。他は 1 バイトも 変わらないが、JSON のスキャナを自前で書くことになる
- 再シリアライズ — parse → 要素を落とす →
to_string。実装は単純だが、整形・キーの順序・ 数値の表現が変わりうる(serde_jsonのpreserve_orderfeature の有無を着手時に数える)
Spec 59 の
omitted { id, from, to }を共有する。from/toは配列の要素の index (Spec 59 は段落の index)。同じツールで 2 つの意味を持つことになるので、idが指す先が 本文か配列かを置き場(PrunedRaw)に持たせる(未決 5)。
ゼロ。 rev2 の 2 点は 2026-09-22 に利用者が裁定した —
(1) _pruned キーを足すことを認める(「圧縮した文字列以外は 1 バイトも変わらない」の射程は
配列型では「対象の配列の中身と _pruned の 1 キー」へ一段ゆるくなる。契約に明記)
(2) 縮んだ効き目で進める(足す母数は Spec 59 と同規模。狭い依頼で 68%・広い依頼で 12%)。
rev1 の未決 5 点 → P0 と査読で全部向きが出た(D1 / D2 / D3 / D4 / D5)。